1 /** 2 * Contains the definition of an affine 4x3 matrix (4 columns, 3 rows) of doubles, and associated functions to transform 3 * it. The matrix is column-major to match OpenGL's interpretation, and it looks like this: 4 * <p> 5 * m00 m10 m20 m30<br> 6 * m01 m11 m21 m31<br> 7 * m02 m12 m22 m32<br> 8 * 9 * @author Richard Greenlees 10 * @author Kai Burjack 11 */ 12 module doml.matrix_4x3d; 13 14 import Math = doml.math; 15 import MemUtil = doml.mem_util; 16 17 import doml.matrix_3d; 18 import doml.matrix_4d; 19 20 import doml.vector_3d; 21 import doml.vector_4d; 22 23 import doml.axis_angle_4d; 24 import doml.quaternion_d; 25 26 /* 27 * The MIT License 28 * 29 * Copyright (c) 2015-2021 Richard Greenlees 30 @$!@$# Translated by jordan4ibanez 31 * 32 * Permission is hereby granted, free of charge, to any person obtaining a copy 33 * of this software and associated documentation files (the "Software"), to deal 34 * in the Software without restriction, including without limitation the rights 35 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 36 * copies of the Software, and to permit persons to whom the Software is 37 * furnished to do so, subject to the following conditions: 38 * 39 * The above copyright notice and this permission notice shall be included in 40 * all copies or substantial portions of the Software. 41 * 42 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 43 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 45 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 46 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 47 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 48 * THE SOFTWARE. 49 */ 50 51 /** 52 * Contains the definition of an affine 4x3 matrix (4 columns, 3 rows) of doubles, and associated functions to transform 53 * it. The matrix is column-major to match OpenGL's interpretation, and it looks like this: 54 * <p> 55 * m00 m10 m20 m30<br> 56 * m01 m11 m21 m31<br> 57 * m02 m12 m22 m32<br> 58 * 59 * @author Richard Greenlees 60 * @author Kai Burjack 61 */ 62 struct Matrix4x3d { 63 64 double m00 = 1.0; 65 double m01 = 0.0; 66 double m02 = 0.0; 67 68 double m10 = 0.0; 69 double m11 = 1.0; 70 double m12 = 0.0; 71 72 double m20 = 0.0; 73 double m21 = 0.0; 74 double m22 = 1.0; 75 76 double m30 = 0.0; 77 double m31 = 0.0; 78 double m32 = 0.0; 79 80 /** 81 * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} 82 * identifying the plane with equation <code>x=-1</code> when using the identity matrix. 83 */ 84 immutable static int PLANE_NX = 0; 85 /** 86 * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} 87 * identifying the plane with equation <code>x=1</code> when using the identity matrix. 88 */ 89 immutable static int PLANE_PX = 1; 90 /** 91 * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} 92 * identifying the plane with equation <code>y=-1</code> when using the identity matrix. 93 */ 94 immutable static int PLANE_NY = 2; 95 /** 96 * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} 97 * identifying the plane with equation <code>y=1</code> when using the identity matrix. 98 */ 99 immutable static int PLANE_PY = 3; 100 /** 101 * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} 102 * identifying the plane with equation <code>z=-1</code> when using the identity matrix. 103 */ 104 immutable static int PLANE_NZ = 4; 105 /** 106 * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} 107 * identifying the plane with equation <code>z=1</code> when using the identity matrix. 108 */ 109 immutable static int PLANE_PZ = 5; 110 111 /** 112 * Bit returned by {@link #properties()} to indicate that the matrix represents the identity transformation. 113 */ 114 immutable static byte PROPERTY_IDENTITY = 1<<2; 115 /** 116 * Bit returned by {@link #properties()} to indicate that the matrix represents a pure translation transformation. 117 */ 118 immutable static byte PROPERTY_TRANSLATION = 1<<3; 119 /** 120 * Bit returned by {@link #properties()} to indicate that the left 3x3 submatrix represents an orthogonal 121 * matrix (i.e. orthonormal basis). 122 */ 123 immutable static byte PROPERTY_ORTHONORMAL = 1<<4; 124 125 126 int properties = PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL; 127 128 /** 129 * Create a new {@link Matrix4x3d} and make it a copy of the given matrix. 130 * 131 * @param mat 132 * the {@link Matrix4x3d} to copy the values from 133 */ 134 this(Matrix4x3d mat) { 135 set(mat); 136 } 137 138 139 /** 140 * Create a new {@link Matrix4x3d} by setting its left 3x3 submatrix to the values of the given {@link Matrix3d} 141 * and the rest to identity. 142 * 143 * @param mat 144 * the {@link Matrix3d} 145 */ 146 this(Matrix3d mat) { 147 set(mat); 148 } 149 150 /** 151 * Create a new 4x4 matrix using the supplied double values. 152 * 153 * @param m00 154 * the value of m00 155 * @param m01 156 * the value of m01 157 * @param m02 158 * the value of m02 159 * @param m10 160 * the value of m10 161 * @param m11 162 * the value of m11 163 * @param m12 164 * the value of m12 165 * @param m20 166 * the value of m20 167 * @param m21 168 * the value of m21 169 * @param m22 170 * the value of m22 171 * @param m30 172 * the value of m30 173 * @param m31 174 * the value of m31 175 * @param m32 176 * the value of m32 177 */ 178 this(double m00, double m01, double m02, 179 double m10, double m11, double m12, 180 double m20, double m21, double m22, 181 double m30, double m31, double m32) { 182 this.m00 = m00; 183 this.m01 = m01; 184 this.m02 = m02; 185 this.m10 = m10; 186 this.m11 = m11; 187 this.m12 = m12; 188 this.m20 = m20; 189 this.m21 = m21; 190 this.m22 = m22; 191 this.m30 = m30; 192 this.m31 = m31; 193 this.m32 = m32; 194 determineProperties(); 195 } 196 197 /** 198 * Assume the given properties about this matrix. 199 * <p> 200 * Use one or multiple of 0, {@link Matrix4x3d#PROPERTY_IDENTITY}, 201 * {@link Matrix4x3d#PROPERTY_TRANSLATION}, {@link Matrix4x3d#PROPERTY_ORTHONORMAL}. 202 * 203 * @param properties 204 * bitset of the properties to assume about this matrix 205 * @return this 206 */ 207 ref public Matrix4x3d assume(int properties) return { 208 this.properties = properties; 209 return this; 210 } 211 212 /** 213 * Compute and set the matrix properties returned by {@link #properties()} based 214 * on the current matrix element values. 215 * 216 * @return this 217 */ 218 ref public Matrix4x3d determineProperties() return { 219 int __properties = 0; 220 if (m00 == 1.0 && m01 == 0.0 && m02 == 0.0 && m10 == 0.0 && m11 == 1.0 && m12 == 0.0 221 && m20 == 0.0 && m21 == 0.0 && m22 == 1.0) { 222 __properties |= PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL; 223 if (m30 == 0.0 && m31 == 0.0 && m32 == 0.0) 224 __properties |= PROPERTY_IDENTITY; 225 } 226 /* 227 * We do not determine orthogonality, since it would require arbitrary epsilons 228 * and is rather expensive (6 dot products) in the worst case. 229 */ 230 this.properties = __properties; 231 return this; 232 } 233 234 public int getproperties() { 235 return properties; 236 } 237 238 ref Matrix4x3d _properties(int properties) return { 239 this.properties = properties; 240 return this; 241 } 242 243 /** 244 * Set the value of the matrix element at column 0 and row 0 without updating the properties of the matrix. 245 * 246 * @param m00 247 * the new value 248 * @return this 249 */ 250 ref Matrix4x3d _m00(double m00) return { 251 this.m00 = m00; 252 return this; 253 } 254 /** 255 * Set the value of the matrix element at column 0 and row 1 without updating the properties of the matrix. 256 * 257 * @param m01 258 * the new value 259 * @return this 260 */ 261 ref Matrix4x3d _m01(double m01) return { 262 this.m01 = m01; 263 return this; 264 } 265 /** 266 * Set the value of the matrix element at column 0 and row 2 without updating the properties of the matrix. 267 * 268 * @param m02 269 * the new value 270 * @return this 271 */ 272 ref Matrix4x3d _m02(double m02) return { 273 this.m02 = m02; 274 return this; 275 } 276 /** 277 * Set the value of the matrix element at column 1 and row 0 without updating the properties of the matrix. 278 * 279 * @param m10 280 * the new value 281 * @return this 282 */ 283 ref Matrix4x3d _m10(double m10) return { 284 this.m10 = m10; 285 return this; 286 } 287 /** 288 * Set the value of the matrix element at column 1 and row 1 without updating the properties of the matrix. 289 * 290 * @param m11 291 * the new value 292 * @return this 293 */ 294 ref Matrix4x3d _m11(double m11) return { 295 this.m11 = m11; 296 return this; 297 } 298 /** 299 * Set the value of the matrix element at column 1 and row 2 without updating the properties of the matrix. 300 * 301 * @param m12 302 * the new value 303 * @return this 304 */ 305 ref Matrix4x3d _m12(double m12) return { 306 this.m12 = m12; 307 return this; 308 } 309 /** 310 * Set the value of the matrix element at column 2 and row 0 without updating the properties of the matrix. 311 * 312 * @param m20 313 * the new value 314 * @return this 315 */ 316 ref Matrix4x3d _m20(double m20) return { 317 this.m20 = m20; 318 return this; 319 } 320 /** 321 * Set the value of the matrix element at column 2 and row 1 without updating the properties of the matrix. 322 * 323 * @param m21 324 * the new value 325 * @return this 326 */ 327 ref Matrix4x3d _m21(double m21) return { 328 this.m21 = m21; 329 return this; 330 } 331 /** 332 * Set the value of the matrix element at column 2 and row 2 without updating the properties of the matrix. 333 * 334 * @param m22 335 * the new value 336 * @return this 337 */ 338 ref Matrix4x3d _m22(double m22) return { 339 this.m22 = m22; 340 return this; 341 } 342 /** 343 * Set the value of the matrix element at column 3 and row 0 without updating the properties of the matrix. 344 * 345 * @param m30 346 * the new value 347 * @return this 348 */ 349 ref Matrix4x3d _m30(double m30) return { 350 this.m30 = m30; 351 return this; 352 } 353 /** 354 * Set the value of the matrix element at column 3 and row 1 without updating the properties of the matrix. 355 * 356 * @param m31 357 * the new value 358 * @return this 359 */ 360 ref Matrix4x3d _m31(double m31) return { 361 this.m31 = m31; 362 return this; 363 } 364 /** 365 * Set the value of the matrix element at column 3 and row 2 without updating the properties of the matrix. 366 * 367 * @param m32 368 * the new value 369 * @return this 370 */ 371 ref Matrix4x3d _m32(double m32) return { 372 this.m32 = m32; 373 return this; 374 } 375 376 /** 377 * Set the value of the matrix element at column 0 and row 0. 378 * 379 * @param m00 380 * the new value 381 * @return this 382 */ 383 ref public Matrix4x3d setm00(double m00) return { 384 this.m00 = m00; 385 properties &= ~PROPERTY_ORTHONORMAL; 386 if (m00 != 1.0) 387 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 388 return this; 389 } 390 /** 391 * Set the value of the matrix element at column 0 and row 1. 392 * 393 * @param m01 394 * the new value 395 * @return this 396 */ 397 ref public Matrix4x3d setm01(double m01) return { 398 this.m01 = m01; 399 properties &= ~PROPERTY_ORTHONORMAL; 400 if (m01 != 0.0) 401 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 402 return this; 403 } 404 /** 405 * Set the value of the matrix element at column 0 and row 2. 406 * 407 * @param m02 408 * the new value 409 * @return this 410 */ 411 ref public Matrix4x3d setm02(double m02) return { 412 this.m02 = m02; 413 properties &= ~PROPERTY_ORTHONORMAL; 414 if (m02 != 0.0) 415 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 416 return this; 417 } 418 /** 419 * Set the value of the matrix element at column 1 and row 0. 420 * 421 * @param m10 422 * the new value 423 * @return this 424 */ 425 ref public Matrix4x3d setm10(double m10) return { 426 this.m10 = m10; 427 properties &= ~PROPERTY_ORTHONORMAL; 428 if (m10 != 0.0) 429 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 430 return this; 431 } 432 /** 433 * Set the value of the matrix element at column 1 and row 1. 434 * 435 * @param m11 436 * the new value 437 * @return this 438 */ 439 ref public Matrix4x3d setm11(double m11) return { 440 this.m11 = m11; 441 properties &= ~PROPERTY_ORTHONORMAL; 442 if (m11 != 1.0) 443 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 444 return this; 445 } 446 /** 447 * Set the value of the matrix element at column 1 and row 2. 448 * 449 * @param m12 450 * the new value 451 * @return this 452 */ 453 ref public Matrix4x3d setm12(double m12) return { 454 this.m12 = m12; 455 properties &= ~PROPERTY_ORTHONORMAL; 456 if (m12 != 0.0) 457 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 458 return this; 459 } 460 /** 461 * Set the value of the matrix element at column 2 and row 0. 462 * 463 * @param m20 464 * the new value 465 * @return this 466 */ 467 ref public Matrix4x3d setm20(double m20) return { 468 this.m20 = m20; 469 properties &= ~PROPERTY_ORTHONORMAL; 470 if (m20 != 0.0) 471 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 472 return this; 473 } 474 /** 475 * Set the value of the matrix element at column 2 and row 1. 476 * 477 * @param m21 478 * the new value 479 * @return this 480 */ 481 ref public Matrix4x3d setm21(double m21) return { 482 this.m21 = m21; 483 properties &= ~PROPERTY_ORTHONORMAL; 484 if (m21 != 0.0) 485 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 486 return this; 487 } 488 /** 489 * Set the value of the matrix element at column 2 and row 2. 490 * 491 * @param m22 492 * the new value 493 * @return this 494 */ 495 ref public Matrix4x3d setm22(double m22) return { 496 this.m22 = m22; 497 properties &= ~PROPERTY_ORTHONORMAL; 498 if (m22 != 1.0) 499 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 500 return this; 501 } 502 /** 503 * Set the value of the matrix element at column 3 and row 0. 504 * 505 * @param m30 506 * the new value 507 * @return this 508 */ 509 ref public Matrix4x3d setm30(double m30) return { 510 this.m30 = m30; 511 if (m30 != 0.0) 512 properties &= ~PROPERTY_IDENTITY; 513 return this; 514 } 515 /** 516 * Set the value of the matrix element at column 3 and row 1. 517 * 518 * @param m31 519 * the new value 520 * @return this 521 */ 522 ref public Matrix4x3d setm31(double m31) return { 523 this.m31 = m31; 524 if (m31 != 0.0) 525 properties &= ~PROPERTY_IDENTITY; 526 return this; 527 } 528 /** 529 * Set the value of the matrix element at column 3 and row 2. 530 * 531 * @param m32 532 * the new value 533 * @return this 534 */ 535 ref public Matrix4x3d setm32(double m32) return { 536 this.m32 = m32; 537 if (m32 != 0.0) 538 properties &= ~PROPERTY_IDENTITY; 539 return this; 540 } 541 542 /** 543 * Reset this matrix to the identity. 544 * <p> 545 * Please note that if a call to {@link #identity()} is immediately followed by a call to: 546 * {@link #translate(double, double, double) translate}, 547 * {@link #rotate(double, double, double, double) rotate}, 548 * {@link #scale(double, double, double) scale}, 549 * {@link #ortho(double, double, double, double, double, double) ortho}, 550 * {@link #ortho2D(double, double, double, double) ortho2D}, 551 * {@link #lookAt(double, double, double, double, double, double, double, double, double) lookAt}, 552 * {@link #lookAlong(double, double, double, double, double, double) lookAlong}, 553 * or any of their overloads, then the call to {@link #identity()} can be omitted and the subsequent call replaced with: 554 * {@link #translation(double, double, double) translation}, 555 * {@link #rotation(double, double, double, double) rotation}, 556 * {@link #scaling(double, double, double) scaling}, 557 * {@link #setOrtho(double, double, double, double, double, double) setOrtho}, 558 * {@link #setOrtho2D(double, double, double, double) setOrtho2D}, 559 * {@link #setLookAt(double, double, double, double, double, double, double, double, double) setLookAt}, 560 * {@link #setLookAlong(double, double, double, double, double, double) setLookAlong}, 561 * or any of their overloads. 562 * 563 * @return this 564 */ 565 ref public Matrix4x3d identity() return { 566 if ((properties & PROPERTY_IDENTITY) != 0) 567 return this; 568 m00 = 1.0; 569 m01 = 0.0; 570 m02 = 0.0; 571 m10 = 0.0; 572 m11 = 1.0; 573 m12 = 0.0; 574 m20 = 0.0; 575 m21 = 0.0; 576 m22 = 1.0; 577 m30 = 0.0; 578 m31 = 0.0; 579 m32 = 0.0; 580 properties = PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL; 581 return this; 582 } 583 584 /** 585 * Store the values of the given matrix <code>m</code> into <code>this</code> matrix. 586 * 587 * @param m 588 * the matrix to copy the values from 589 * @return this 590 */ 591 ref public Matrix4x3d set(Matrix4x3d m) return { 592 m00 = m.m00; 593 m01 = m.m01; 594 m02 = m.m02; 595 m10 = m.m10; 596 m11 = m.m11; 597 m12 = m.m12; 598 m20 = m.m20; 599 m21 = m.m21; 600 m22 = m.m22; 601 m30 = m.m30; 602 m31 = m.m31; 603 m32 = m.m32; 604 properties = m.properties; 605 return this; 606 } 607 608 609 /** 610 * Store the values of the upper 4x3 submatrix of <code>m</code> into <code>this</code> matrix. 611 * 612 * @see Matrix4d#get4x3(Matrix4x3d) 613 * 614 * @param m 615 * the matrix to copy the values from 616 * @return this 617 */ 618 ref public Matrix4x3d set(Matrix4d m) return { 619 m00 = m.m00; 620 m01 = m.m01; 621 m02 = m.m02; 622 m10 = m.m10; 623 m11 = m.m11; 624 m12 = m.m12; 625 m20 = m.m20; 626 m21 = m.m21; 627 m22 = m.m22; 628 m30 = m.m30; 629 m31 = m.m31; 630 m32 = m.m32; 631 properties = m.properties & (PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 632 return this; 633 } 634 635 public Matrix4d get(ref Matrix4d dest) { 636 return dest.set4x3(this); 637 } 638 639 /** 640 * Set the left 3x3 submatrix of this {@link Matrix4x3d} to the given {@link Matrix3d} 641 * and the rest to identity. 642 * 643 * @see #Matrix4x3d(Matrix3d) 644 * 645 * @param mat 646 * the {@link Matrix3d} 647 * @return this 648 */ 649 ref public Matrix4x3d set(Matrix3d mat) return { 650 m00 = mat.m00; 651 m01 = mat.m01; 652 m02 = mat.m02; 653 m10 = mat.m10; 654 m11 = mat.m11; 655 m12 = mat.m12; 656 m20 = mat.m20; 657 m21 = mat.m21; 658 m22 = mat.m22; 659 m30 = 0.0; 660 m31 = 0.0; 661 m32 = 0.0; 662 return determineProperties(); 663 } 664 665 666 /** 667 * Set the four columns of this matrix to the supplied vectors, respectively. 668 * 669 * @param col0 670 * the first column 671 * @param col1 672 * the second column 673 * @param col2 674 * the third column 675 * @param col3 676 * the fourth column 677 * @return this 678 */ 679 ref public Matrix4x3d set(Vector3d col0, 680 Vector3d col1, 681 Vector3d col2, 682 Vector3d col3) return { 683 this.m00 = col0.x; 684 this.m01 = col0.y; 685 this.m02 = col0.z; 686 this.m10 = col1.x; 687 this.m11 = col1.y; 688 this.m12 = col1.z; 689 this.m20 = col2.x; 690 this.m21 = col2.y; 691 this.m22 = col2.z; 692 this.m30 = col3.x; 693 this.m31 = col3.y; 694 this.m32 = col3.z; 695 return determineProperties(); 696 } 697 698 /** 699 * Set the left 3x3 submatrix of this {@link Matrix4x3d} to that of the given {@link Matrix4x3d} 700 * and don't change the other elements. 701 * 702 * @param mat 703 * the {@link Matrix4x3d} 704 * @return this 705 */ 706 ref public Matrix4x3d set3x3(Matrix4x3d mat) return { 707 m00 = mat.m00; 708 m01 = mat.m01; 709 m02 = mat.m02; 710 m10 = mat.m10; 711 m11 = mat.m11; 712 m12 = mat.m12; 713 m20 = mat.m20; 714 m21 = mat.m21; 715 m22 = mat.m22; 716 properties &= mat.properties; 717 return this; 718 } 719 720 /** 721 * Set this matrix to be equivalent to the rotation specified by the given {@link AxisAngle4d}. 722 * 723 * @param axisAngle 724 * the {@link AxisAngle4d} 725 * @return this 726 */ 727 ref public Matrix4x3d set(AxisAngle4d axisAngle) return { 728 double x = axisAngle.x; 729 double y = axisAngle.y; 730 double z = axisAngle.z; 731 double angle = axisAngle.angle; 732 double invLength = Math.invsqrt(x*x + y*y + z*z); 733 x *= invLength; 734 y *= invLength; 735 z *= invLength; 736 double s = Math.sin(angle); 737 double c = Math.cosFromSin(s, angle); 738 double omc = 1.0 - c; 739 m00 = c + x*x*omc; 740 m11 = c + y*y*omc; 741 m22 = c + z*z*omc; 742 double tmp1 = x*y*omc; 743 double tmp2 = z*s; 744 m10 = tmp1 - tmp2; 745 m01 = tmp1 + tmp2; 746 tmp1 = x*z*omc; 747 tmp2 = y*s; 748 m20 = tmp1 + tmp2; 749 m02 = tmp1 - tmp2; 750 tmp1 = y*z*omc; 751 tmp2 = x*s; 752 m21 = tmp1 - tmp2; 753 m12 = tmp1 + tmp2; 754 m30 = 0.0; 755 m31 = 0.0; 756 m32 = 0.0; 757 properties = PROPERTY_ORTHONORMAL; 758 return this; 759 } 760 761 762 /** 763 * Set this matrix to be equivalent to the rotation - and possibly scaling - specified by the given {@link Quaterniond}. 764 * <p> 765 * This method is equivalent to calling: <code>rotation(q)</code> 766 * 767 * @param q 768 * the {@link Quaterniond} 769 * @return this 770 */ 771 ref public Matrix4x3d set(Quaterniond q) return { 772 return rotation(q); 773 } 774 775 /** 776 * Multiply this matrix by the supplied <code>right</code> matrix. 777 * <p> 778 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the <code>right</code> matrix, 779 * then the new matrix will be <code>M * R</code>. So when transforming a 780 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 781 * transformation of the right matrix will be applied first! 782 * 783 * @param right 784 * the right operand of the multiplication 785 * @return this 786 */ 787 ref public Matrix4x3d mul(Matrix4x3d right) return { 788 mul(right, this); 789 return this; 790 } 791 792 public Matrix4x3d mul(Matrix4x3d right, ref Matrix4x3d dest) { 793 if ((properties & PROPERTY_IDENTITY) != 0) 794 return dest.set(right); 795 else if ((right.properties & PROPERTY_IDENTITY) != 0) 796 return dest.set(this); 797 else if ((properties & PROPERTY_TRANSLATION) != 0) 798 return mulTranslation(right, dest); 799 return mulGeneric(right, dest); 800 } 801 private Matrix4x3d mulGeneric(Matrix4x3d right, ref Matrix4x3d dest) { 802 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 803 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 804 double __m20 = this.m20, __m21 = this.m21, __m22 = this.m22; 805 double rm00 = right.m00, rm01 = right.m01, rm02 = right.m02; 806 double rm10 = right.m10, rm11 = right.m11, rm12 = right.m12; 807 double rm20 = right.m20, rm21 = right.m21, rm22 = right.m22; 808 double rm30 = right.m30, rm31 = right.m31, rm32 = right.m32; 809 return dest 810 ._m00(Math.fma(__m00, rm00, Math.fma(__m10, rm01, __m20 * rm02))) 811 ._m01(Math.fma(__m01, rm00, Math.fma(__m11, rm01, __m21 * rm02))) 812 ._m02(Math.fma(__m02, rm00, Math.fma(__m12, rm01, __m22 * rm02))) 813 ._m10(Math.fma(__m00, rm10, Math.fma(__m10, rm11, __m20 * rm12))) 814 ._m11(Math.fma(__m01, rm10, Math.fma(__m11, rm11, __m21 * rm12))) 815 ._m12(Math.fma(__m02, rm10, Math.fma(__m12, rm11, __m22 * rm12))) 816 ._m20(Math.fma(__m00, rm20, Math.fma(__m10, rm21, __m20 * rm22))) 817 ._m21(Math.fma(__m01, rm20, Math.fma(__m11, rm21, __m21 * rm22))) 818 ._m22(Math.fma(__m02, rm20, Math.fma(__m12, rm21, __m22 * rm22))) 819 ._m30(Math.fma(__m00, rm30, Math.fma(__m10, rm31, Math.fma(__m20, rm32, m30)))) 820 ._m31(Math.fma(__m01, rm30, Math.fma(__m11, rm31, Math.fma(__m21, rm32, m31)))) 821 ._m32(Math.fma(__m02, rm30, Math.fma(__m12, rm31, Math.fma(__m22, rm32, m32)))) 822 ._properties(properties & right.properties & PROPERTY_ORTHONORMAL); 823 } 824 825 826 public Matrix4x3d mulTranslation(Matrix4x3d right, ref Matrix4x3d dest) { 827 return dest 828 ._m00(right.m00) 829 ._m01(right.m01) 830 ._m02(right.m02) 831 ._m10(right.m10) 832 ._m11(right.m11) 833 ._m12(right.m12) 834 ._m20(right.m20) 835 ._m21(right.m21) 836 ._m22(right.m22) 837 ._m30(right.m30 + m30) 838 ._m31(right.m31 + m31) 839 ._m32(right.m32 + m32) 840 ._properties(right.properties & PROPERTY_ORTHONORMAL); 841 } 842 843 /** 844 * Multiply <code>this</code> orthographic projection matrix by the supplied <code>view</code> matrix. 845 * <p> 846 * If <code>M</code> is <code>this</code> matrix and <code>V</code> the <code>view</code> matrix, 847 * then the new matrix will be <code>M * V</code>. So when transforming a 848 * vector <code>v</code> with the new matrix by using <code>M * V * v</code>, the 849 * transformation of the <code>view</code> matrix will be applied first! 850 * 851 * @param view 852 * the matrix which to multiply <code>this</code> with 853 * @return this 854 */ 855 ref public Matrix4x3d mulOrtho(Matrix4x3d view) return { 856 mulOrtho(view, this); 857 return this; 858 } 859 860 public Matrix4x3d mulOrtho(Matrix4x3d view, ref Matrix4x3d dest) { 861 double nm00 = m00 * view.m00; 862 double nm01 = m11 * view.m01; 863 double nm02 = m22 * view.m02; 864 double nm10 = m00 * view.m10; 865 double nm11 = m11 * view.m11; 866 double nm12 = m22 * view.m12; 867 double nm20 = m00 * view.m20; 868 double nm21 = m11 * view.m21; 869 double nm22 = m22 * view.m22; 870 double nm30 = m00 * view.m30 + m30; 871 double nm31 = m11 * view.m31 + m31; 872 double nm32 = m22 * view.m32 + m32; 873 dest.m00 = nm00; 874 dest.m01 = nm01; 875 dest.m02 = nm02; 876 dest.m10 = nm10; 877 dest.m11 = nm11; 878 dest.m12 = nm12; 879 dest.m20 = nm20; 880 dest.m21 = nm21; 881 dest.m22 = nm22; 882 dest.m30 = nm30; 883 dest.m31 = nm31; 884 dest.m32 = nm32; 885 dest.properties = (this.properties & view.properties & PROPERTY_ORTHONORMAL); 886 return dest; 887 } 888 889 /** 890 * Multiply <code>this</code> by the 4x3 matrix with the column vectors <code>(rm00, rm01, rm02)</code>, 891 * <code>(rm10, rm11, rm12)</code>, <code>(rm20, rm21, rm22)</code> and <code>(0, 0, 0)</code>. 892 * <p> 893 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the specified matrix, 894 * then the new matrix will be <code>M * R</code>. So when transforming a 895 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 896 * transformation of the <code>R</code> matrix will be applied first! 897 * 898 * @param rm00 899 * the value of the m00 element 900 * @param rm01 901 * the value of the m01 element 902 * @param rm02 903 * the value of the m02 element 904 * @param rm10 905 * the value of the m10 element 906 * @param rm11 907 * the value of the m11 element 908 * @param rm12 909 * the value of the m12 element 910 * @param rm20 911 * the value of the m20 element 912 * @param rm21 913 * the value of the m21 element 914 * @param rm22 915 * the value of the m22 element 916 * @return this 917 */ 918 ref public Matrix4x3d mul3x3( 919 double rm00, double rm01, double rm02, 920 double rm10, double rm11, double rm12, 921 double rm20, double rm21, double rm22) return { 922 mul3x3(rm00, rm01, rm02, rm10, rm11, rm12, rm20, rm21, rm22, this); 923 return this; 924 } 925 public Matrix4x3d mul3x3( 926 double rm00, double rm01, double rm02, 927 double rm10, double rm11, double rm12, 928 double rm20, double rm21, double rm22, 929 ref Matrix4x3d dest) { 930 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 931 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 932 double m20 = this.m20, m21 = this.m21, m22 = this.m22; 933 return dest 934 ._m00(Math.fma(m00, rm00, Math.fma(m10, rm01, m20 * rm02))) 935 ._m01(Math.fma(m01, rm00, Math.fma(m11, rm01, m21 * rm02))) 936 ._m02(Math.fma(m02, rm00, Math.fma(m12, rm01, m22 * rm02))) 937 ._m10(Math.fma(m00, rm10, Math.fma(m10, rm11, m20 * rm12))) 938 ._m11(Math.fma(m01, rm10, Math.fma(m11, rm11, m21 * rm12))) 939 ._m12(Math.fma(m02, rm10, Math.fma(m12, rm11, m22 * rm12))) 940 ._m20(Math.fma(m00, rm20, Math.fma(m10, rm21, m20 * rm22))) 941 ._m21(Math.fma(m01, rm20, Math.fma(m11, rm21, m21 * rm22))) 942 ._m22(Math.fma(m02, rm20, Math.fma(m12, rm21, m22 * rm22))) 943 ._m30(m30) 944 ._m31(m31) 945 ._m32(m32) 946 ._properties(0); 947 } 948 949 /** 950 * Component-wise add <code>this</code> and <code>other</code> 951 * by first multiplying each component of <code>other</code> by <code>otherFactor</code> and 952 * adding that result to <code>this</code>. 953 * <p> 954 * The matrix <code>other</code> will not be changed. 955 * 956 * @param other 957 * the other matrix 958 * @param otherFactor 959 * the factor to multiply each of the other matrix's components 960 * @return this 961 */ 962 ref public Matrix4x3d fma(Matrix4x3d other, double otherFactor) return { 963 fma(other, otherFactor, this); 964 return this; 965 } 966 967 public Matrix4x3d fma(Matrix4x3d other, double otherFactor, ref Matrix4x3d dest) { 968 dest 969 ._m00(Math.fma(other.m00, otherFactor, m00)) 970 ._m01(Math.fma(other.m01, otherFactor, m01)) 971 ._m02(Math.fma(other.m02, otherFactor, m02)) 972 ._m10(Math.fma(other.m10, otherFactor, m10)) 973 ._m11(Math.fma(other.m11, otherFactor, m11)) 974 ._m12(Math.fma(other.m12, otherFactor, m12)) 975 ._m20(Math.fma(other.m20, otherFactor, m20)) 976 ._m21(Math.fma(other.m21, otherFactor, m21)) 977 ._m22(Math.fma(other.m22, otherFactor, m22)) 978 ._m30(Math.fma(other.m30, otherFactor, m30)) 979 ._m31(Math.fma(other.m31, otherFactor, m31)) 980 ._m32(Math.fma(other.m32, otherFactor, m32)) 981 ._properties(0); 982 return dest; 983 } 984 985 /** 986 * Component-wise add <code>this</code> and <code>other</code>. 987 * 988 * @param other 989 * the other addend 990 * @return this 991 */ 992 ref public Matrix4x3d add(Matrix4x3d other) return { 993 add(other, this); 994 return this; 995 } 996 997 public Matrix4x3d add(Matrix4x3d other, ref Matrix4x3d dest) { 998 dest.m00 = m00 + other.m00; 999 dest.m01 = m01 + other.m01; 1000 dest.m02 = m02 + other.m02; 1001 dest.m10 = m10 + other.m10; 1002 dest.m11 = m11 + other.m11; 1003 dest.m12 = m12 + other.m12; 1004 dest.m20 = m20 + other.m20; 1005 dest.m21 = m21 + other.m21; 1006 dest.m22 = m22 + other.m22; 1007 dest.m30 = m30 + other.m30; 1008 dest.m31 = m31 + other.m31; 1009 dest.m32 = m32 + other.m32; 1010 dest.properties = 0; 1011 return dest; 1012 } 1013 1014 1015 /** 1016 * Component-wise subtract <code>subtrahend</code> from <code>this</code>. 1017 * 1018 * @param subtrahend 1019 * the subtrahend 1020 * @return this 1021 */ 1022 ref public Matrix4x3d sub(Matrix4x3d subtrahend) return { 1023 sub(subtrahend, this); 1024 return this; 1025 } 1026 1027 public Matrix4x3d sub(Matrix4x3d subtrahend, ref Matrix4x3d dest) { 1028 dest.m00 = m00 - subtrahend.m00; 1029 dest.m01 = m01 - subtrahend.m01; 1030 dest.m02 = m02 - subtrahend.m02; 1031 dest.m10 = m10 - subtrahend.m10; 1032 dest.m11 = m11 - subtrahend.m11; 1033 dest.m12 = m12 - subtrahend.m12; 1034 dest.m20 = m20 - subtrahend.m20; 1035 dest.m21 = m21 - subtrahend.m21; 1036 dest.m22 = m22 - subtrahend.m22; 1037 dest.m30 = m30 - subtrahend.m30; 1038 dest.m31 = m31 - subtrahend.m31; 1039 dest.m32 = m32 - subtrahend.m32; 1040 dest.properties = 0; 1041 return dest; 1042 } 1043 1044 /** 1045 * Component-wise multiply <code>this</code> by <code>other</code>. 1046 * 1047 * @param other 1048 * the other matrix 1049 * @return this 1050 */ 1051 ref public Matrix4x3d mulComponentWise(Matrix4x3d other) return { 1052 mulComponentWise(other, this); 1053 return this; 1054 } 1055 1056 public Matrix4x3d mulComponentWise(Matrix4x3d other, ref Matrix4x3d dest) { 1057 dest.m00 = m00 * other.m00; 1058 dest.m01 = m01 * other.m01; 1059 dest.m02 = m02 * other.m02; 1060 dest.m10 = m10 * other.m10; 1061 dest.m11 = m11 * other.m11; 1062 dest.m12 = m12 * other.m12; 1063 dest.m20 = m20 * other.m20; 1064 dest.m21 = m21 * other.m21; 1065 dest.m22 = m22 * other.m22; 1066 dest.m30 = m30 * other.m30; 1067 dest.m31 = m31 * other.m31; 1068 dest.m32 = m32 * other.m32; 1069 dest.properties = 0; 1070 return dest; 1071 } 1072 1073 /** 1074 * Set the values within this matrix to the supplied double values. The matrix will look like this:<br><br> 1075 * 1076 * m00, m10, m20, m30<br> 1077 * m01, m11, m21, m31<br> 1078 * m02, m12, m22, m32<br> 1079 * 1080 * @param m00 1081 * the new value of m00 1082 * @param m01 1083 * the new value of m01 1084 * @param m02 1085 * the new value of m02 1086 * @param m10 1087 * the new value of m10 1088 * @param m11 1089 * the new value of m11 1090 * @param m12 1091 * the new value of m12 1092 * @param m20 1093 * the new value of m20 1094 * @param m21 1095 * the new value of m21 1096 * @param m22 1097 * the new value of m22 1098 * @param m30 1099 * the new value of m30 1100 * @param m31 1101 * the new value of m31 1102 * @param m32 1103 * the new value of m32 1104 * @return this 1105 */ 1106 ref public Matrix4x3d set(double m00, double m01, double m02, 1107 double m10, double m11, double m12, 1108 double m20, double m21, double m22, 1109 double m30, double m31, double m32) return { 1110 this.m00 = m00; 1111 this.m10 = m10; 1112 this.m20 = m20; 1113 this.m30 = m30; 1114 this.m01 = m01; 1115 this.m11 = m11; 1116 this.m21 = m21; 1117 this.m31 = m31; 1118 this.m02 = m02; 1119 this.m12 = m12; 1120 this.m22 = m22; 1121 this.m32 = m32; 1122 return determineProperties(); 1123 } 1124 1125 /** 1126 * Set the values in the matrix using a double array that contains the matrix elements in column-major order. 1127 * <p> 1128 * The results will look like this:<br><br> 1129 * 1130 * 0, 3, 6, 9<br> 1131 * 1, 4, 7, 10<br> 1132 * 2, 5, 8, 11<br> 1133 * 1134 * @see #set(double[]) 1135 * 1136 * @param m 1137 * the array to read the matrix values from 1138 * @param off 1139 * the offset into the array 1140 * @return this 1141 */ 1142 ref public Matrix4x3d set(double[] m, int off) return { 1143 m00 = m[off+0]; 1144 m01 = m[off+1]; 1145 m02 = m[off+2]; 1146 m10 = m[off+3]; 1147 m11 = m[off+4]; 1148 m12 = m[off+5]; 1149 m20 = m[off+6]; 1150 m21 = m[off+7]; 1151 m22 = m[off+8]; 1152 m30 = m[off+9]; 1153 m31 = m[off+10]; 1154 m32 = m[off+11]; 1155 return determineProperties(); 1156 } 1157 1158 /** 1159 * Set the values in the matrix using a double array that contains the matrix elements in column-major order. 1160 * <p> 1161 * The results will look like this:<br><br> 1162 * 1163 * 0, 3, 6, 9<br> 1164 * 1, 4, 7, 10<br> 1165 * 2, 5, 8, 11<br> 1166 * 1167 * @see #set(double[], int) 1168 * 1169 * @param m 1170 * the array to read the matrix values from 1171 * @return this 1172 */ 1173 ref public Matrix4x3d set(double[] m) return { 1174 return set(m, 0); 1175 } 1176 1177 1178 1179 public double determinant() { 1180 return (m00 * m11 - m01 * m10) * m22 1181 + (m02 * m10 - m00 * m12) * m21 1182 + (m01 * m12 - m02 * m11) * m20; 1183 } 1184 1185 /** 1186 * Invert this matrix. 1187 * 1188 * @return this 1189 */ 1190 ref public Matrix4x3d invert() return { 1191 invert(this); 1192 return this; 1193 } 1194 1195 public Matrix4x3d invert(ref Matrix4x3d dest) { 1196 if ((properties & PROPERTY_IDENTITY) != 0) 1197 return dest.identity(); 1198 else if ((properties & PROPERTY_ORTHONORMAL) != 0) 1199 return invertOrthonormal(dest); 1200 return invertGeneric(dest); 1201 } 1202 private Matrix4x3d invertGeneric(ref Matrix4x3d dest) { 1203 double m11m00 = m00 * m11, m10m01 = m01 * m10, m10m02 = m02 * m10; 1204 double m12m00 = m00 * m12, m12m01 = m01 * m12, m11m02 = m02 * m11; 1205 double s = 1.0 / ((m11m00 - m10m01) * m22 + (m10m02 - m12m00) * m21 + (m12m01 - m11m02) * m20); 1206 double m10m22 = m10 * m22, m10m21 = m10 * m21, m11m22 = m11 * m22; 1207 double m11m20 = m11 * m20, m12m21 = m12 * m21, m12m20 = m12 * m20; 1208 double m20m02 = m20 * m02, m20m01 = m20 * m01, m21m02 = m21 * m02; 1209 double m21m00 = m21 * m00, m22m01 = m22 * m01, m22m00 = m22 * m00; 1210 double nm00 = (m11m22 - m12m21) * s; 1211 double nm01 = (m21m02 - m22m01) * s; 1212 double nm02 = (m12m01 - m11m02) * s; 1213 double nm10 = (m12m20 - m10m22) * s; 1214 double nm11 = (m22m00 - m20m02) * s; 1215 double nm12 = (m10m02 - m12m00) * s; 1216 double nm20 = (m10m21 - m11m20) * s; 1217 double nm21 = (m20m01 - m21m00) * s; 1218 double nm22 = (m11m00 - m10m01) * s; 1219 double nm30 = (m10m22 * m31 - m10m21 * m32 + m11m20 * m32 - m11m22 * m30 + m12m21 * m30 - m12m20 * m31) * s; 1220 double nm31 = (m20m02 * m31 - m20m01 * m32 + m21m00 * m32 - m21m02 * m30 + m22m01 * m30 - m22m00 * m31) * s; 1221 double nm32 = (m11m02 * m30 - m12m01 * m30 + m12m00 * m31 - m10m02 * m31 + m10m01 * m32 - m11m00 * m32) * s; 1222 dest.m00 = nm00; 1223 dest.m01 = nm01; 1224 dest.m02 = nm02; 1225 dest.m10 = nm10; 1226 dest.m11 = nm11; 1227 dest.m12 = nm12; 1228 dest.m20 = nm20; 1229 dest.m21 = nm21; 1230 dest.m22 = nm22; 1231 dest.m30 = nm30; 1232 dest.m31 = nm31; 1233 dest.m32 = nm32; 1234 dest.properties = 0; 1235 return dest; 1236 } 1237 private Matrix4x3d invertOrthonormal(ref Matrix4x3d dest) { 1238 double nm30 = -(m00 * m30 + m01 * m31 + m02 * m32); 1239 double nm31 = -(m10 * m30 + m11 * m31 + m12 * m32); 1240 double nm32 = -(m20 * m30 + m21 * m31 + m22 * m32); 1241 double m01 = this.m01; 1242 double m02 = this.m02; 1243 double m12 = this.m12; 1244 dest.m00 = m00; 1245 dest.m01 = m10; 1246 dest.m02 = m20; 1247 dest.m10 = m01; 1248 dest.m11 = m11; 1249 dest.m12 = m21; 1250 dest.m20 = m02; 1251 dest.m21 = m12; 1252 dest.m22 = m22; 1253 dest.m30 = nm30; 1254 dest.m31 = nm31; 1255 dest.m32 = nm32; 1256 dest.properties = PROPERTY_ORTHONORMAL; 1257 return dest; 1258 } 1259 1260 public Matrix4x3d invertOrtho(ref Matrix4x3d dest) { 1261 double invM00 = 1.0 / m00; 1262 double invM11 = 1.0 / m11; 1263 double invM22 = 1.0 / m22; 1264 dest.set(invM00, 0, 0, 1265 0, invM11, 0, 1266 0, 0, invM22, 1267 -m30 * invM00, -m31 * invM11, -m32 * invM22); 1268 dest.properties = 0; 1269 return dest; 1270 } 1271 1272 /** 1273 * Invert <code>this</code> orthographic projection matrix. 1274 * <p> 1275 * This method can be used to quickly obtain the inverse of an orthographic projection matrix. 1276 * 1277 * @return this 1278 */ 1279 ref public Matrix4x3d invertOrtho() return { 1280 invertOrtho(this); 1281 return this; 1282 } 1283 1284 /** 1285 * Transpose only the left 3x3 submatrix of this matrix and set the rest of the matrix elements to identity. 1286 * 1287 * @return this 1288 */ 1289 ref public Matrix4x3d transpose3x3() return { 1290 transpose3x3(this); 1291 return this; 1292 } 1293 1294 public Matrix4x3d transpose3x3(ref Matrix4x3d dest) { 1295 double nm00 = m00; 1296 double nm01 = m10; 1297 double nm02 = m20; 1298 double nm10 = m01; 1299 double nm11 = m11; 1300 double nm12 = m21; 1301 double nm20 = m02; 1302 double nm21 = m12; 1303 double nm22 = m22; 1304 dest.m00 = nm00; 1305 dest.m01 = nm01; 1306 dest.m02 = nm02; 1307 dest.m10 = nm10; 1308 dest.m11 = nm11; 1309 dest.m12 = nm12; 1310 dest.m20 = nm20; 1311 dest.m21 = nm21; 1312 dest.m22 = nm22; 1313 dest.properties = properties; 1314 return dest; 1315 } 1316 1317 public Matrix3d transpose3x3(Matrix3d dest) { 1318 dest.m00 = (m00); 1319 dest.m01 = (m10); 1320 dest.m02 = (m20); 1321 dest.m10 = (m01); 1322 dest.m11 = (m11); 1323 dest.m12 = (m21); 1324 dest.m20 = (m02); 1325 dest.m21 = (m12); 1326 dest.m22 = (m22); 1327 return dest; 1328 } 1329 1330 /** 1331 * Set this matrix to be a simple translation matrix. 1332 * <p> 1333 * The resulting matrix can be multiplied against another transformation 1334 * matrix to obtain an additional translation. 1335 * 1336 * @param x 1337 * the offset to translate in x 1338 * @param y 1339 * the offset to translate in y 1340 * @param z 1341 * the offset to translate in z 1342 * @return this 1343 */ 1344 ref public Matrix4x3d translation(double x, double y, double z) return { 1345 if ((properties & PROPERTY_IDENTITY) == 0) 1346 this.identity(); 1347 m30 = x; 1348 m31 = y; 1349 m32 = z; 1350 properties = PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL; 1351 return this; 1352 } 1353 1354 1355 /** 1356 * Set this matrix to be a simple translation matrix. 1357 * <p> 1358 * The resulting matrix can be multiplied against another transformation 1359 * matrix to obtain an additional translation. 1360 * 1361 * @param offset 1362 * the offsets in x, y and z to translate 1363 * @return this 1364 */ 1365 ref public Matrix4x3d translation(Vector3d offset) return { 1366 return translation(offset.x, offset.y, offset.z); 1367 } 1368 1369 /** 1370 * Set only the translation components <code>(m30, m31, m32)</code> of this matrix to the given values <code>(x, y, z)</code>. 1371 * <p> 1372 * To build a translation matrix instead, use {@link #translation(double, double, double)}. 1373 * To apply a translation, use {@link #translate(double, double, double)}. 1374 * 1375 * @see #translation(double, double, double) 1376 * @see #translate(double, double, double) 1377 * 1378 * @param x 1379 * the units to translate in x 1380 * @param y 1381 * the units to translate in y 1382 * @param z 1383 * the units to translate in z 1384 * @return this 1385 */ 1386 ref public Matrix4x3d setTranslation(double x, double y, double z) return { 1387 m30 = x; 1388 m31 = y; 1389 m32 = z; 1390 properties &= ~(PROPERTY_IDENTITY); 1391 return this; 1392 } 1393 1394 /** 1395 * 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>. 1396 * <p> 1397 * To build a translation matrix instead, use {@link #translation(Vector3d)}. 1398 * To apply a translation, use {@link #translate(Vector3d)}. 1399 * 1400 * @see #translation(Vector3d) 1401 * @see #translate(Vector3d) 1402 * 1403 * @param xyz 1404 * the units to translate in <code>(x, y, z)</code> 1405 * @return this 1406 */ 1407 ref public Matrix4x3d setTranslation(Vector3d xyz) return { 1408 return setTranslation(xyz.x, xyz.y, xyz.z); 1409 } 1410 1411 public Vector3d getTranslation(ref Vector3d dest) { 1412 dest.x = m30; 1413 dest.y = m31; 1414 dest.z = m32; 1415 return dest; 1416 } 1417 1418 public Vector3d getScale(ref Vector3d dest) { 1419 dest.x = Math.sqrt(m00 * m00 + m01 * m01 + m02 * m02); 1420 dest.y = Math.sqrt(m10 * m10 + m11 * m11 + m12 * m12); 1421 dest.z = Math.sqrt(m20 * m20 + m21 * m21 + m22 * m22); 1422 return dest; 1423 } 1424 1425 /** 1426 * Get the current values of <code>this</code> matrix and store them into 1427 * <code>dest</code>. 1428 * <p> 1429 * This is the reverse method of {@link #set(Matrix4x3d)} and allows to obtain 1430 * intermediate calculation results when chaining multiple transformations. 1431 * 1432 * @see #set(Matrix4x3d) 1433 * 1434 * @param dest 1435 * the destination matrix 1436 * @return the passed in destination 1437 */ 1438 public Matrix4x3d get(ref Matrix4x3d dest) { 1439 return dest.set(this); 1440 } 1441 1442 public Quaterniond getUnnormalizedRotation(Quaterniond dest) { 1443 return dest.setFromUnnormalized(this); 1444 } 1445 1446 public Quaterniond getNormalizedRotation(Quaterniond dest) { 1447 return dest.setFromNormalized(this); 1448 } 1449 1450 public double[] get(double[] arr, int offset) { 1451 arr[offset+0] = m00; 1452 arr[offset+1] = m01; 1453 arr[offset+2] = m02; 1454 arr[offset+3] = m10; 1455 arr[offset+4] = m11; 1456 arr[offset+5] = m12; 1457 arr[offset+6] = m20; 1458 arr[offset+7] = m21; 1459 arr[offset+8] = m22; 1460 arr[offset+9] = m30; 1461 arr[offset+10] = m31; 1462 arr[offset+11] = m32; 1463 return arr; 1464 } 1465 1466 public double[] get(double[] arr) { 1467 return get(arr, 0); 1468 } 1469 1470 1471 public double[] get4x4(double[] arr, int offset) { 1472 MemUtil.copy4x4(this, arr, offset); 1473 return arr; 1474 } 1475 1476 public double[] get4x4(double[] arr) { 1477 return get4x4(arr, 0); 1478 } 1479 1480 1481 public double[] getTransposed(double[] arr, int offset) { 1482 arr[offset+0] = m00; 1483 arr[offset+1] = m10; 1484 arr[offset+2] = m20; 1485 arr[offset+3] = m30; 1486 arr[offset+4] = m01; 1487 arr[offset+5] = m11; 1488 arr[offset+6] = m21; 1489 arr[offset+7] = m31; 1490 arr[offset+8] = m02; 1491 arr[offset+9] = m12; 1492 arr[offset+10] = m22; 1493 arr[offset+11] = m32; 1494 return arr; 1495 } 1496 1497 public double[] getTransposed(double[] arr) { 1498 return getTransposed(arr, 0); 1499 } 1500 1501 /** 1502 * Set all the values within this matrix to 0. 1503 * 1504 * @return this 1505 */ 1506 ref public Matrix4x3d zero() return { 1507 m00 = 0.0; 1508 m01 = 0.0; 1509 m02 = 0.0; 1510 m10 = 0.0; 1511 m11 = 0.0; 1512 m12 = 0.0; 1513 m20 = 0.0; 1514 m21 = 0.0; 1515 m22 = 0.0; 1516 m30 = 0.0; 1517 m31 = 0.0; 1518 m32 = 0.0; 1519 properties = 0; 1520 return this; 1521 } 1522 1523 /** 1524 * Set this matrix to be a simple scale matrix, which scales all axes uniformly by the given factor. 1525 * <p> 1526 * The resulting matrix can be multiplied against another transformation 1527 * matrix to obtain an additional scaling. 1528 * <p> 1529 * In order to post-multiply a scaling transformation directly to a 1530 * matrix, use {@link #scale(double) scale()} instead. 1531 * 1532 * @see #scale(double) 1533 * 1534 * @param factor 1535 * the scale factor in x, y and z 1536 * @return this 1537 */ 1538 ref public Matrix4x3d scaling(double factor) return { 1539 return scaling(factor, factor, factor); 1540 } 1541 1542 /** 1543 * Set this matrix to be a simple scale matrix. 1544 * 1545 * @param x 1546 * the scale in x 1547 * @param y 1548 * the scale in y 1549 * @param z 1550 * the scale in z 1551 * @return this 1552 */ 1553 ref public Matrix4x3d scaling(double x, double y, double z) return { 1554 if ((properties & PROPERTY_IDENTITY) == 0) 1555 this.identity(); 1556 m00 = x; 1557 m11 = y; 1558 m22 = z; 1559 bool one = Math.absEqualsOne(x) && Math.absEqualsOne(y) && Math.absEqualsOne(z); 1560 properties = one ? PROPERTY_ORTHONORMAL : 0; 1561 return this; 1562 } 1563 1564 /** 1565 * Set this matrix to be a simple scale matrix which scales the base axes by 1566 * <code>xyz.x</code>, <code>xyz.y</code> and <code>xyz.z</code>, respectively. 1567 * <p> 1568 * The resulting matrix can be multiplied against another transformation 1569 * matrix to obtain an additional scaling. 1570 * <p> 1571 * In order to post-multiply a scaling transformation directly to a 1572 * matrix use {@link #scale(Vector3d) scale()} instead. 1573 * 1574 * @see #scale(Vector3d) 1575 * 1576 * @param xyz 1577 * the scale in x, y and z, respectively 1578 * @return this 1579 */ 1580 ref public Matrix4x3d scaling(Vector3d xyz) return { 1581 return scaling(xyz.x, xyz.y, xyz.z); 1582 } 1583 1584 /** 1585 * Set this matrix to a rotation matrix which rotates the given radians about a given axis. 1586 * <p> 1587 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1588 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1589 * When used with a left-handed coordinate system, the rotation is clockwise. 1590 * <p> 1591 * From <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">Wikipedia</a> 1592 * 1593 * @param angle 1594 * the angle in radians 1595 * @param x 1596 * the x-coordinate of the axis to rotate about 1597 * @param y 1598 * the y-coordinate of the axis to rotate about 1599 * @param z 1600 * the z-coordinate of the axis to rotate about 1601 * @return this 1602 */ 1603 ref public Matrix4x3d rotation(double angle, double x, double y, double z) return { 1604 if (y == 0.0 && z == 0.0 && Math.absEqualsOne(x)) 1605 rotationX(x * angle); 1606 else if (x == 0.0 && z == 0.0 && Math.absEqualsOne(y)) 1607 rotationY(y * angle); 1608 else if (x == 0.0 && y == 0.0 && Math.absEqualsOne(z)) 1609 rotationZ(z * angle); 1610 else 1611 rotationInternal(angle, x, y, z); 1612 return this; 1613 } 1614 private Matrix4x3d rotationInternal(double angle, double x, double y, double z) { 1615 double sin = Math.sin(angle); 1616 double cos = Math.cosFromSin(sin, angle); 1617 double C = 1.0 - cos; 1618 double xy = x * y, xz = x * z, yz = y * z; 1619 m00 = cos + x * x * C; 1620 m01 = xy * C + z * sin; 1621 m02 = xz * C - y * sin; 1622 m10 = xy * C - z * sin; 1623 m11 = cos + y * y * C; 1624 m12 = yz * C + x * sin; 1625 m20 = xz * C + y * sin; 1626 m21 = yz * C - x * sin; 1627 m22 = cos + z * z * C; 1628 m30 = 0.0; 1629 m31 = 0.0; 1630 m32 = 0.0; 1631 properties = PROPERTY_ORTHONORMAL; 1632 return this; 1633 } 1634 1635 /** 1636 * Set this matrix to a rotation transformation about the X axis. 1637 * <p> 1638 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1639 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1640 * When used with a left-handed coordinate system, the rotation is clockwise. 1641 * <p> 1642 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 1643 * 1644 * @param ang 1645 * the angle in radians 1646 * @return this 1647 */ 1648 ref public Matrix4x3d rotationX(double ang) return { 1649 double sin, cos; 1650 sin = Math.sin(ang); 1651 cos = Math.cosFromSin(sin, ang); 1652 m00 = 1.0; 1653 m01 = 0.0; 1654 m02 = 0.0; 1655 m10 = 0.0; 1656 m11 = cos; 1657 m12 = sin; 1658 m20 = 0.0; 1659 m21 = -sin; 1660 m22 = cos; 1661 m30 = 0.0; 1662 m31 = 0.0; 1663 m32 = 0.0; 1664 properties = PROPERTY_ORTHONORMAL; 1665 return this; 1666 } 1667 1668 /** 1669 * Set this matrix to a rotation transformation about the Y axis. 1670 * <p> 1671 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1672 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1673 * When used with a left-handed coordinate system, the rotation is clockwise. 1674 * <p> 1675 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 1676 * 1677 * @param ang 1678 * the angle in radians 1679 * @return this 1680 */ 1681 ref public Matrix4x3d rotationY(double ang) return { 1682 double sin, cos; 1683 sin = Math.sin(ang); 1684 cos = Math.cosFromSin(sin, ang); 1685 m00 = cos; 1686 m01 = 0.0; 1687 m02 = -sin; 1688 m10 = 0.0; 1689 m11 = 1.0; 1690 m12 = 0.0; 1691 m20 = sin; 1692 m21 = 0.0; 1693 m22 = cos; 1694 m30 = 0.0; 1695 m31 = 0.0; 1696 m32 = 0.0; 1697 properties = PROPERTY_ORTHONORMAL; 1698 return this; 1699 } 1700 1701 /** 1702 * Set this matrix to a rotation transformation about the Z axis. 1703 * <p> 1704 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1705 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1706 * When used with a left-handed coordinate system, the rotation is clockwise. 1707 * <p> 1708 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 1709 * 1710 * @param ang 1711 * the angle in radians 1712 * @return this 1713 */ 1714 ref public Matrix4x3d rotationZ(double ang) return { 1715 double sin, cos; 1716 sin = Math.sin(ang); 1717 cos = Math.cosFromSin(sin, ang); 1718 m00 = cos; 1719 m01 = sin; 1720 m02 = 0.0; 1721 m10 = -sin; 1722 m11 = cos; 1723 m12 = 0.0; 1724 m20 = 0.0; 1725 m21 = 0.0; 1726 m22 = 1.0; 1727 m30 = 0.0; 1728 m31 = 0.0; 1729 m32 = 0.0; 1730 properties = PROPERTY_ORTHONORMAL; 1731 return this; 1732 } 1733 1734 /** 1735 * Set this matrix to a rotation of <code>angleX</code> radians about the X axis, followed by a rotation 1736 * of <code>angleY</code> radians about the Y axis and followed by a rotation of <code>angleZ</code> radians about the Z axis. 1737 * <p> 1738 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1739 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1740 * When used with a left-handed coordinate system, the rotation is clockwise. 1741 * <p> 1742 * This method is equivalent to calling: <code>rotationX(angleX).rotateY(angleY).rotateZ(angleZ)</code> 1743 * 1744 * @param angleX 1745 * the angle to rotate about X 1746 * @param angleY 1747 * the angle to rotate about Y 1748 * @param angleZ 1749 * the angle to rotate about Z 1750 * @return this 1751 */ 1752 ref public Matrix4x3d rotationXYZ(double angleX, double angleY, double angleZ) return { 1753 double sinX = Math.sin(angleX); 1754 double cosX = Math.cosFromSin(sinX, angleX); 1755 double sinY = Math.sin(angleY); 1756 double cosY = Math.cosFromSin(sinY, angleY); 1757 double sinZ = Math.sin(angleZ); 1758 double cosZ = Math.cosFromSin(sinZ, angleZ); 1759 double m_sinX = -sinX; 1760 double m_sinY = -sinY; 1761 double m_sinZ = -sinZ; 1762 1763 // rotateX 1764 double nm11 = cosX; 1765 double nm12 = sinX; 1766 double nm21 = m_sinX; 1767 double nm22 = cosX; 1768 // rotateY 1769 double nm00 = cosY; 1770 double nm01 = nm21 * m_sinY; 1771 double nm02 = nm22 * m_sinY; 1772 m20 = sinY; 1773 m21 = nm21 * cosY; 1774 m22 = nm22 * cosY; 1775 // rotateZ 1776 m00 = nm00 * cosZ; 1777 m01 = nm01 * cosZ + nm11 * sinZ; 1778 m02 = nm02 * cosZ + nm12 * sinZ; 1779 m10 = nm00 * m_sinZ; 1780 m11 = nm01 * m_sinZ + nm11 * cosZ; 1781 m12 = nm02 * m_sinZ + nm12 * cosZ; 1782 // set last column to identity 1783 m30 = 0.0; 1784 m31 = 0.0; 1785 m32 = 0.0; 1786 properties = PROPERTY_ORTHONORMAL; 1787 return this; 1788 } 1789 1790 /** 1791 * Set this matrix to a rotation of <code>angleZ</code> radians about the Z axis, followed by a rotation 1792 * of <code>angleY</code> radians about the Y axis and followed by a rotation of <code>angleX</code> radians about the X axis. 1793 * <p> 1794 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1795 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1796 * When used with a left-handed coordinate system, the rotation is clockwise. 1797 * <p> 1798 * This method is equivalent to calling: <code>rotationZ(angleZ).rotateY(angleY).rotateX(angleX)</code> 1799 * 1800 * @param angleZ 1801 * the angle to rotate about Z 1802 * @param angleY 1803 * the angle to rotate about Y 1804 * @param angleX 1805 * the angle to rotate about X 1806 * @return this 1807 */ 1808 ref public Matrix4x3d rotationZYX(double angleZ, double angleY, double angleX) return { 1809 double sinX = Math.sin(angleX); 1810 double cosX = Math.cosFromSin(sinX, angleX); 1811 double sinY = Math.sin(angleY); 1812 double cosY = Math.cosFromSin(sinY, angleY); 1813 double sinZ = Math.sin(angleZ); 1814 double cosZ = Math.cosFromSin(sinZ, angleZ); 1815 double m_sinZ = -sinZ; 1816 double m_sinY = -sinY; 1817 double m_sinX = -sinX; 1818 1819 // rotateZ 1820 double nm00 = cosZ; 1821 double nm01 = sinZ; 1822 double nm10 = m_sinZ; 1823 double nm11 = cosZ; 1824 // rotateY 1825 double nm20 = nm00 * sinY; 1826 double nm21 = nm01 * sinY; 1827 double nm22 = cosY; 1828 m00 = nm00 * cosY; 1829 m01 = nm01 * cosY; 1830 m02 = m_sinY; 1831 // rotateX 1832 m10 = nm10 * cosX + nm20 * sinX; 1833 m11 = nm11 * cosX + nm21 * sinX; 1834 m12 = nm22 * sinX; 1835 m20 = nm10 * m_sinX + nm20 * cosX; 1836 m21 = nm11 * m_sinX + nm21 * cosX; 1837 m22 = nm22 * cosX; 1838 // set last column to identity 1839 m30 = 0.0; 1840 m31 = 0.0; 1841 m32 = 0.0; 1842 properties = PROPERTY_ORTHONORMAL; 1843 return this; 1844 } 1845 1846 /** 1847 * Set this matrix to a rotation of <code>angleY</code> radians about the Y axis, followed by a rotation 1848 * of <code>angleX</code> radians about the X axis and followed by a rotation of <code>angleZ</code> radians about the Z axis. 1849 * <p> 1850 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1851 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1852 * When used with a left-handed coordinate system, the rotation is clockwise. 1853 * <p> 1854 * This method is equivalent to calling: <code>rotationY(angleY).rotateX(angleX).rotateZ(angleZ)</code> 1855 * 1856 * @param angleY 1857 * the angle to rotate about Y 1858 * @param angleX 1859 * the angle to rotate about X 1860 * @param angleZ 1861 * the angle to rotate about Z 1862 * @return this 1863 */ 1864 ref public Matrix4x3d rotationYXZ(double angleY, double angleX, double angleZ) return { 1865 double sinX = Math.sin(angleX); 1866 double cosX = Math.cosFromSin(sinX, angleX); 1867 double sinY = Math.sin(angleY); 1868 double cosY = Math.cosFromSin(sinY, angleY); 1869 double sinZ = Math.sin(angleZ); 1870 double cosZ = Math.cosFromSin(sinZ, angleZ); 1871 double m_sinY = -sinY; 1872 double m_sinX = -sinX; 1873 double m_sinZ = -sinZ; 1874 1875 // rotateY 1876 double nm00 = cosY; 1877 double nm02 = m_sinY; 1878 double nm20 = sinY; 1879 double nm22 = cosY; 1880 // rotateX 1881 double nm10 = nm20 * sinX; 1882 double nm11 = cosX; 1883 double nm12 = nm22 * sinX; 1884 m20 = nm20 * cosX; 1885 m21 = m_sinX; 1886 m22 = nm22 * cosX; 1887 // rotateZ 1888 m00 = nm00 * cosZ + nm10 * sinZ; 1889 m01 = nm11 * sinZ; 1890 m02 = nm02 * cosZ + nm12 * sinZ; 1891 m10 = nm00 * m_sinZ + nm10 * cosZ; 1892 m11 = nm11 * cosZ; 1893 m12 = nm02 * m_sinZ + nm12 * cosZ; 1894 // set last column to identity 1895 m30 = 0.0; 1896 m31 = 0.0; 1897 m32 = 0.0; 1898 properties = PROPERTY_ORTHONORMAL; 1899 return this; 1900 } 1901 1902 /** 1903 * 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 1904 * of <code>angleY</code> radians about the Y axis and followed by a rotation of <code>angleZ</code> radians about the Z axis. 1905 * <p> 1906 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1907 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1908 * When used with a left-handed coordinate system, the rotation is clockwise. 1909 * 1910 * @param angleX 1911 * the angle to rotate about X 1912 * @param angleY 1913 * the angle to rotate about Y 1914 * @param angleZ 1915 * the angle to rotate about Z 1916 * @return this 1917 */ 1918 ref public Matrix4x3d setRotationXYZ(double angleX, double angleY, double angleZ) return { 1919 double sinX = Math.sin(angleX); 1920 double cosX = Math.cosFromSin(sinX, angleX); 1921 double sinY = Math.sin(angleY); 1922 double cosY = Math.cosFromSin(sinY, angleY); 1923 double sinZ = Math.sin(angleZ); 1924 double cosZ = Math.cosFromSin(sinZ, angleZ); 1925 double m_sinX = -sinX; 1926 double m_sinY = -sinY; 1927 double m_sinZ = -sinZ; 1928 1929 // rotateX 1930 double nm11 = cosX; 1931 double nm12 = sinX; 1932 double nm21 = m_sinX; 1933 double nm22 = cosX; 1934 // rotateY 1935 double nm00 = cosY; 1936 double nm01 = nm21 * m_sinY; 1937 double nm02 = nm22 * m_sinY; 1938 m20 = sinY; 1939 m21 = nm21 * cosY; 1940 m22 = nm22 * cosY; 1941 // rotateZ 1942 m00 = nm00 * cosZ; 1943 m01 = nm01 * cosZ + nm11 * sinZ; 1944 m02 = nm02 * cosZ + nm12 * sinZ; 1945 m10 = nm00 * m_sinZ; 1946 m11 = nm01 * m_sinZ + nm11 * cosZ; 1947 m12 = nm02 * m_sinZ + nm12 * cosZ; 1948 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 1949 return this; 1950 } 1951 1952 /** 1953 * 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 1954 * of <code>angleY</code> radians about the Y axis and followed by a rotation of <code>angleX</code> radians about the X axis. 1955 * <p> 1956 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1957 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1958 * When used with a left-handed coordinate system, the rotation is clockwise. 1959 * 1960 * @param angleZ 1961 * the angle to rotate about Z 1962 * @param angleY 1963 * the angle to rotate about Y 1964 * @param angleX 1965 * the angle to rotate about X 1966 * @return this 1967 */ 1968 ref public Matrix4x3d setRotationZYX(double angleZ, double angleY, double angleX) return { 1969 double sinX = Math.sin(angleX); 1970 double cosX = Math.cosFromSin(sinX, angleX); 1971 double sinY = Math.sin(angleY); 1972 double cosY = Math.cosFromSin(sinY, angleY); 1973 double sinZ = Math.sin(angleZ); 1974 double cosZ = Math.cosFromSin(sinZ, angleZ); 1975 double m_sinZ = -sinZ; 1976 double m_sinY = -sinY; 1977 double m_sinX = -sinX; 1978 1979 // rotateZ 1980 double nm00 = cosZ; 1981 double nm01 = sinZ; 1982 double nm10 = m_sinZ; 1983 double nm11 = cosZ; 1984 // rotateY 1985 double nm20 = nm00 * sinY; 1986 double nm21 = nm01 * sinY; 1987 double nm22 = cosY; 1988 m00 = nm00 * cosY; 1989 m01 = nm01 * cosY; 1990 m02 = m_sinY; 1991 // rotateX 1992 m10 = nm10 * cosX + nm20 * sinX; 1993 m11 = nm11 * cosX + nm21 * sinX; 1994 m12 = nm22 * sinX; 1995 m20 = nm10 * m_sinX + nm20 * cosX; 1996 m21 = nm11 * m_sinX + nm21 * cosX; 1997 m22 = nm22 * cosX; 1998 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 1999 return this; 2000 } 2001 2002 /** 2003 * 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 2004 * of <code>angleX</code> radians about the X axis and followed by a rotation of <code>angleZ</code> radians about the Z axis. 2005 * <p> 2006 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2007 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2008 * When used with a left-handed coordinate system, the rotation is clockwise. 2009 * 2010 * @param angleY 2011 * the angle to rotate about Y 2012 * @param angleX 2013 * the angle to rotate about X 2014 * @param angleZ 2015 * the angle to rotate about Z 2016 * @return this 2017 */ 2018 ref public Matrix4x3d setRotationYXZ(double angleY, double angleX, double angleZ) return { 2019 double sinX = Math.sin(angleX); 2020 double cosX = Math.cosFromSin(sinX, angleX); 2021 double sinY = Math.sin(angleY); 2022 double cosY = Math.cosFromSin(sinY, angleY); 2023 double sinZ = Math.sin(angleZ); 2024 double cosZ = Math.cosFromSin(sinZ, angleZ); 2025 double m_sinY = -sinY; 2026 double m_sinX = -sinX; 2027 double m_sinZ = -sinZ; 2028 2029 // rotateY 2030 double nm00 = cosY; 2031 double nm02 = m_sinY; 2032 double nm20 = sinY; 2033 double nm22 = cosY; 2034 // rotateX 2035 double nm10 = nm20 * sinX; 2036 double nm11 = cosX; 2037 double nm12 = nm22 * sinX; 2038 m20 = nm20 * cosX; 2039 m21 = m_sinX; 2040 m22 = nm22 * cosX; 2041 // rotateZ 2042 m00 = nm00 * cosZ + nm10 * sinZ; 2043 m01 = nm11 * sinZ; 2044 m02 = nm02 * cosZ + nm12 * sinZ; 2045 m10 = nm00 * m_sinZ + nm10 * cosZ; 2046 m11 = nm11 * cosZ; 2047 m12 = nm02 * m_sinZ + nm12 * cosZ; 2048 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2049 return this; 2050 } 2051 2052 /** 2053 * Set this matrix to a rotation matrix which rotates the given radians about a given axis. 2054 * <p> 2055 * The axis described by the <code>axis</code> vector needs to be a unit vector. 2056 * <p> 2057 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2058 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2059 * When used with a left-handed coordinate system, the rotation is clockwise. 2060 * 2061 * @param angle 2062 * the angle in radians 2063 * @param axis 2064 * the axis to rotate about 2065 * @return this 2066 */ 2067 ref public Matrix4x3d rotation(double angle, Vector3d axis) return { 2068 return rotation(angle, axis.x, axis.y, axis.z); 2069 } 2070 2071 public Vector4d transform(Vector4d v) { 2072 return v.mul(this); 2073 } 2074 2075 public Vector4d transform(Vector4d v, Vector4d dest) { 2076 return v.mul(this, dest); 2077 } 2078 2079 public Vector3d transformPosition(ref Vector3d v) { 2080 v.set(m00 * v.x + m10 * v.y + m20 * v.z + m30, 2081 m01 * v.x + m11 * v.y + m21 * v.z + m31, 2082 m02 * v.x + m12 * v.y + m22 * v.z + m32); 2083 return v; 2084 } 2085 2086 public Vector3d transformPosition(ref Vector3d v, ref Vector3d dest) { 2087 dest.set(m00 * v.x + m10 * v.y + m20 * v.z + m30, 2088 m01 * v.x + m11 * v.y + m21 * v.z + m31, 2089 m02 * v.x + m12 * v.y + m22 * v.z + m32); 2090 return dest; 2091 } 2092 2093 public Vector3d transformDirection(ref Vector3d v) { 2094 v.set(m00 * v.x + m10 * v.y + m20 * v.z, 2095 m01 * v.x + m11 * v.y + m21 * v.z, 2096 m02 * v.x + m12 * v.y + m22 * v.z); 2097 return v; 2098 } 2099 2100 public Vector3d transformDirection(ref Vector3d v, ref Vector3d dest) { 2101 dest.set(m00 * v.x + m10 * v.y + m20 * v.z, 2102 m01 * v.x + m11 * v.y + m21 * v.z, 2103 m02 * v.x + m12 * v.y + m22 * v.z); 2104 return dest; 2105 } 2106 2107 /** 2108 * Set the left 3x3 submatrix of this {@link Matrix4x3d} to the given {@link Matrix3d} and don't change the other elements. 2109 * 2110 * @param mat 2111 * the 3x3 matrix 2112 * @return this 2113 */ 2114 ref public Matrix4x3d set3x3(Matrix3d mat) return { 2115 m00 = mat.m00; 2116 m01 = mat.m01; 2117 m02 = mat.m02; 2118 m10 = mat.m10; 2119 m11 = mat.m11; 2120 m12 = mat.m12; 2121 m20 = mat.m20; 2122 m21 = mat.m21; 2123 m22 = mat.m22; 2124 properties = 0; 2125 return this; 2126 } 2127 2128 2129 public Matrix4x3d scale(Vector3d xyz, ref Matrix4x3d dest) { 2130 return scale(xyz.x, xyz.y, xyz.z, dest); 2131 } 2132 2133 /** 2134 * Apply scaling to this matrix by scaling the base axes by the given <code>xyz.x</code>, 2135 * <code>xyz.y</code> and <code>xyz.z</code> factors, respectively. 2136 * <p> 2137 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2138 * then the new matrix will be <code>M * S</code>. So when transforming a 2139 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 2140 * scaling will be applied first! 2141 * 2142 * @param xyz 2143 * the factors of the x, y and z component, respectively 2144 * @return this 2145 */ 2146 ref public Matrix4x3d scale(Vector3d xyz) return { 2147 scale(xyz.x, xyz.y, xyz.z, this); 2148 return this; 2149 } 2150 2151 public Matrix4x3d scale(double x, double y, double z, ref Matrix4x3d dest) { 2152 if ((properties & PROPERTY_IDENTITY) != 0) 2153 return dest.scaling(x, y, z); 2154 return scaleGeneric(x, y, z, dest); 2155 } 2156 private Matrix4x3d scaleGeneric(double x, double y, double z, ref Matrix4x3d dest) { 2157 dest.m00 = m00 * x; 2158 dest.m01 = m01 * x; 2159 dest.m02 = m02 * x; 2160 dest.m10 = m10 * y; 2161 dest.m11 = m11 * y; 2162 dest.m12 = m12 * y; 2163 dest.m20 = m20 * z; 2164 dest.m21 = m21 * z; 2165 dest.m22 = m22 * z; 2166 dest.m30 = m30; 2167 dest.m31 = m31; 2168 dest.m32 = m32; 2169 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 2170 return dest; 2171 } 2172 2173 /** 2174 * Apply scaling to <code>this</code> matrix by scaling the base axes by the given x, 2175 * y and z factors. 2176 * <p> 2177 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2178 * then the new matrix will be <code>M * S</code>. So when transforming a 2179 * vector <code>v</code> with the new matrix by using <code>M * S * v</code> 2180 * , the scaling will be applied first! 2181 * 2182 * @param x 2183 * the factor of the x component 2184 * @param y 2185 * the factor of the y component 2186 * @param z 2187 * the factor of the z component 2188 * @return this 2189 */ 2190 ref public Matrix4x3d scale(double x, double y, double z) return { 2191 scale(x, y, z, this); 2192 return this; 2193 } 2194 2195 public Matrix4x3d scale(double xyz, ref Matrix4x3d dest) { 2196 return scale(xyz, xyz, xyz, dest); 2197 } 2198 2199 /** 2200 * Apply scaling to this matrix by uniformly scaling all base axes by the given xyz factor. 2201 * <p> 2202 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2203 * then the new matrix will be <code>M * S</code>. So when transforming a 2204 * vector <code>v</code> with the new matrix by using <code>M * S * v</code> 2205 * , the scaling will be applied first! 2206 * 2207 * @see #scale(double, double, double) 2208 * 2209 * @param xyz 2210 * the factor for all components 2211 * @return this 2212 */ 2213 ref public Matrix4x3d scale(double xyz) return { 2214 return scale(xyz, xyz, xyz); 2215 } 2216 2217 public Matrix4x3d scaleXY(double x, double y, ref Matrix4x3d dest) { 2218 return scale(x, y, 1.0, dest); 2219 } 2220 2221 /** 2222 * Apply scaling to this matrix by scaling the X axis by <code>x</code> and the Y axis by <code>y</code>. 2223 * <p> 2224 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2225 * then the new matrix will be <code>M * S</code>. So when transforming a 2226 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 2227 * scaling will be applied first! 2228 * 2229 * @param x 2230 * the factor of the x component 2231 * @param y 2232 * the factor of the y component 2233 * @return this 2234 */ 2235 ref public Matrix4x3d scaleXY(double x, double y) return { 2236 return scale(x, y, 1.0); 2237 } 2238 2239 public Matrix4x3d scaleAround(double sx, double sy, double sz, double ox, double oy, double oz, ref Matrix4x3d dest) { 2240 double nm30 = m00 * ox + m10 * oy + m20 * oz + m30; 2241 double nm31 = m01 * ox + m11 * oy + m21 * oz + m31; 2242 double nm32 = m02 * ox + m12 * oy + m22 * oz + m32; 2243 bool one = Math.absEqualsOne(sx) && Math.absEqualsOne(sy) && Math.absEqualsOne(sz); 2244 return dest 2245 ._m00(m00 * sx) 2246 ._m01(m01 * sx) 2247 ._m02(m02 * sx) 2248 ._m10(m10 * sy) 2249 ._m11(m11 * sy) 2250 ._m12(m12 * sy) 2251 ._m20(m20 * sz) 2252 ._m21(m21 * sz) 2253 ._m22(m22 * sz) 2254 ._m30(-dest.m00 * ox - dest.m10 * oy - dest.m20 * oz + nm30) 2255 ._m31(-dest.m01 * ox - dest.m11 * oy - dest.m21 * oz + nm31) 2256 ._m32(-dest.m02 * ox - dest.m12 * oy - dest.m22 * oz + nm32) 2257 ._properties(properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | (one ? 0 : PROPERTY_ORTHONORMAL))); 2258 } 2259 2260 /** 2261 * Apply scaling to this matrix by scaling the base axes by the given sx, 2262 * sy and sz factors while using <code>(ox, oy, oz)</code> as the scaling origin. 2263 * <p> 2264 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2265 * then the new matrix will be <code>M * S</code>. So when transforming a 2266 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 2267 * scaling will be applied first! 2268 * <p> 2269 * This method is equivalent to calling: <code>translate(ox, oy, oz).scale(sx, sy, sz).translate(-ox, -oy, -oz)</code> 2270 * 2271 * @param sx 2272 * the scaling factor of the x component 2273 * @param sy 2274 * the scaling factor of the y component 2275 * @param sz 2276 * the scaling factor of the z component 2277 * @param ox 2278 * the x coordinate of the scaling origin 2279 * @param oy 2280 * the y coordinate of the scaling origin 2281 * @param oz 2282 * the z coordinate of the scaling origin 2283 * @return this 2284 */ 2285 ref public Matrix4x3d scaleAround(double sx, double sy, double sz, double ox, double oy, double oz) return { 2286 scaleAround(sx, sy, sz, ox, oy, oz, this); 2287 return this; 2288 } 2289 2290 /** 2291 * Apply scaling to this matrix by scaling all three base axes by the given <code>factor</code> 2292 * while using <code>(ox, oy, oz)</code> as the scaling origin. 2293 * <p> 2294 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2295 * then the new matrix will be <code>M * S</code>. So when transforming a 2296 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 2297 * scaling will be applied first! 2298 * <p> 2299 * This method is equivalent to calling: <code>translate(ox, oy, oz).scale(factor).translate(-ox, -oy, -oz)</code> 2300 * 2301 * @param factor 2302 * the scaling factor for all three axes 2303 * @param ox 2304 * the x coordinate of the scaling origin 2305 * @param oy 2306 * the y coordinate of the scaling origin 2307 * @param oz 2308 * the z coordinate of the scaling origin 2309 * @return this 2310 */ 2311 ref public Matrix4x3d scaleAround(double factor, double ox, double oy, double oz) return { 2312 scaleAround(factor, factor, factor, ox, oy, oz, this); 2313 return this; 2314 } 2315 2316 public Matrix4x3d scaleAround(double factor, double ox, double oy, double oz, ref Matrix4x3d dest) { 2317 return scaleAround(factor, factor, factor, ox, oy, oz, dest); 2318 } 2319 2320 public Matrix4x3d scaleLocal(double x, double y, double z, ref Matrix4x3d dest) { 2321 if ((properties & PROPERTY_IDENTITY) != 0) 2322 return dest.scaling(x, y, z); 2323 2324 double nm00 = x * m00; 2325 double nm01 = y * m01; 2326 double nm02 = z * m02; 2327 double nm10 = x * m10; 2328 double nm11 = y * m11; 2329 double nm12 = z * m12; 2330 double nm20 = x * m20; 2331 double nm21 = y * m21; 2332 double nm22 = z * m22; 2333 double nm30 = x * m30; 2334 double nm31 = y * m31; 2335 double nm32 = z * m32; 2336 dest.m00 = nm00; 2337 dest.m01 = nm01; 2338 dest.m02 = nm02; 2339 dest.m10 = nm10; 2340 dest.m11 = nm11; 2341 dest.m12 = nm12; 2342 dest.m20 = nm20; 2343 dest.m21 = nm21; 2344 dest.m22 = nm22; 2345 dest.m30 = nm30; 2346 dest.m31 = nm31; 2347 dest.m32 = nm32; 2348 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 2349 return dest; 2350 } 2351 2352 /** 2353 * Pre-multiply scaling to this matrix by scaling the base axes by the given x, 2354 * y and z factors. 2355 * <p> 2356 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2357 * then the new matrix will be <code>S * M</code>. So when transforming a 2358 * vector <code>v</code> with the new matrix by using <code>S * M * v</code>, the 2359 * scaling will be applied last! 2360 * 2361 * @param x 2362 * the factor of the x component 2363 * @param y 2364 * the factor of the y component 2365 * @param z 2366 * the factor of the z component 2367 * @return this 2368 */ 2369 ref public Matrix4x3d scaleLocal(double x, double y, double z) return { 2370 scaleLocal(x, y, z, this); 2371 return this; 2372 } 2373 2374 public Matrix4x3d rotate(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2375 if ((properties & PROPERTY_IDENTITY) != 0) 2376 return dest.rotation(ang, x, y, z); 2377 else if ((properties & PROPERTY_TRANSLATION) != 0) 2378 return rotateTranslation(ang, x, y, z, dest); 2379 return rotateGeneric(ang, x, y, z, dest); 2380 } 2381 private Matrix4x3d rotateGeneric(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2382 if (y == 0.0 && z == 0.0 && Math.absEqualsOne(x)) 2383 return rotateX(x * ang, dest); 2384 else if (x == 0.0 && z == 0.0 && Math.absEqualsOne(y)) 2385 return rotateY(y * ang, dest); 2386 else if (x == 0.0 && y == 0.0 && Math.absEqualsOne(z)) 2387 return rotateZ(z * ang, dest); 2388 return rotateGenericInternal(ang, x, y, z, dest); 2389 } 2390 private Matrix4x3d rotateGenericInternal(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2391 double s = Math.sin(ang); 2392 double c = Math.cosFromSin(s, ang); 2393 double C = 1.0 - c; 2394 double xx = x * x, xy = x * y, xz = x * z; 2395 double yy = y * y, yz = y * z; 2396 double zz = z * z; 2397 double rm00 = xx * C + c; 2398 double rm01 = xy * C + z * s; 2399 double rm02 = xz * C - y * s; 2400 double rm10 = xy * C - z * s; 2401 double rm11 = yy * C + c; 2402 double rm12 = yz * C + x * s; 2403 double rm20 = xz * C + y * s; 2404 double rm21 = yz * C - x * s; 2405 double rm22 = zz * C + c; 2406 // add temporaries for dependent values 2407 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 2408 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 2409 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 2410 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 2411 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 2412 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 2413 // set non-dependent values directly 2414 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 2415 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 2416 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 2417 // set other values 2418 dest.m00 = nm00; 2419 dest.m01 = nm01; 2420 dest.m02 = nm02; 2421 dest.m10 = nm10; 2422 dest.m11 = nm11; 2423 dest.m12 = nm12; 2424 dest.m30 = m30; 2425 dest.m31 = m31; 2426 dest.m32 = m32; 2427 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2428 return dest; 2429 } 2430 2431 /** 2432 * Apply rotation to this matrix by rotating the given amount of radians 2433 * about the given axis specified as x, y and z components. 2434 * <p> 2435 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2436 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2437 * When used with a left-handed coordinate system, the rotation is clockwise. 2438 * <p> 2439 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2440 * then the new matrix will be <code>M * R</code>. So when transforming a 2441 * vector <code>v</code> with the new matrix by using <code>M * R * v</code> 2442 * , the rotation will be applied first! 2443 * <p> 2444 * In order to set the matrix to a rotation matrix without post-multiplying the rotation 2445 * transformation, use {@link #rotation(double, double, double, double) rotation()}. 2446 * 2447 * @see #rotation(double, double, double, double) 2448 * 2449 * @param ang 2450 * the angle is in radians 2451 * @param x 2452 * the x component of the axis 2453 * @param y 2454 * the y component of the axis 2455 * @param z 2456 * the z component of the axis 2457 * @return this 2458 */ 2459 ref public Matrix4x3d rotate(double ang, double x, double y, double z) return { 2460 rotate(ang, x, y, z, this); 2461 return this; 2462 } 2463 2464 /** 2465 * Apply rotation to this matrix, which is assumed to only contain a translation, by rotating the given amount of radians 2466 * about the specified <code>(x, y, z)</code> axis and store the result in <code>dest</code>. 2467 * <p> 2468 * This method assumes <code>this</code> to only contain a translation. 2469 * <p> 2470 * The axis described by the three components needs to be a unit vector. 2471 * <p> 2472 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2473 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2474 * When used with a left-handed coordinate system, the rotation is clockwise. 2475 * <p> 2476 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2477 * then the new matrix will be <code>M * R</code>. So when transforming a 2478 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 2479 * rotation will be applied first! 2480 * <p> 2481 * In order to set the matrix to a rotation matrix without post-multiplying the rotation 2482 * transformation, use {@link #rotation(double, double, double, double) rotation()}. 2483 * <p> 2484 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2485 * 2486 * @see #rotation(double, double, double, double) 2487 * 2488 * @param ang 2489 * the angle in radians 2490 * @param x 2491 * the x component of the axis 2492 * @param y 2493 * the y component of the axis 2494 * @param z 2495 * the z component of the axis 2496 * @param dest 2497 * will hold the result 2498 * @return dest 2499 */ 2500 public Matrix4x3d rotateTranslation(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2501 double tx = m30, ty = m31, tz = m32; 2502 if (y == 0.0 && z == 0.0 && Math.absEqualsOne(x)) 2503 return dest.rotationX(x * ang).setTranslation(tx, ty, tz); 2504 else if (x == 0.0 && z == 0.0 && Math.absEqualsOne(y)) 2505 return dest.rotationY(y * ang).setTranslation(tx, ty, tz); 2506 else if (x == 0.0 && y == 0.0 && Math.absEqualsOne(z)) 2507 return dest.rotationZ(z * ang).setTranslation(tx, ty, tz); 2508 return rotateTranslationInternal(ang, x, y, z, dest); 2509 } 2510 private Matrix4x3d rotateTranslationInternal(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2511 double s = Math.sin(ang); 2512 double c = Math.cosFromSin(s, ang); 2513 double C = 1.0 - c; 2514 double xx = x * x, xy = x * y, xz = x * z; 2515 double yy = y * y, yz = y * z; 2516 double zz = z * z; 2517 double rm00 = xx * C + c; 2518 double rm01 = xy * C + z * s; 2519 double rm02 = xz * C - y * s; 2520 double rm10 = xy * C - z * s; 2521 double rm11 = yy * C + c; 2522 double rm12 = yz * C + x * s; 2523 double rm20 = xz * C + y * s; 2524 double rm21 = yz * C - x * s; 2525 double rm22 = zz * C + c; 2526 dest.m20 = rm20; 2527 dest.m21 = rm21; 2528 dest.m22 = rm22; 2529 dest.m00 = rm00; 2530 dest.m01 = rm01; 2531 dest.m02 = rm02; 2532 dest.m10 = rm10; 2533 dest.m11 = rm11; 2534 dest.m12 = rm12; 2535 dest.m30 = m30; 2536 dest.m31 = m31; 2537 dest.m32 = m32; 2538 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2539 return dest; 2540 } 2541 2542 /** 2543 * Apply the rotation transformation of the given {@link Quaterniond} to this matrix while using <code>(ox, oy, oz)</code> as the rotation origin. 2544 * <p> 2545 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2546 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2547 * When used with a left-handed coordinate system, the rotation is clockwise. 2548 * <p> 2549 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 2550 * then the new matrix will be <code>M * Q</code>. So when transforming a 2551 * vector <code>v</code> with the new matrix by using <code>M * Q * v</code>, 2552 * the quaternion rotation will be applied first! 2553 * <p> 2554 * This method is equivalent to calling: <code>translate(ox, oy, oz).rotate(quat).translate(-ox, -oy, -oz)</code> 2555 * <p> 2556 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 2557 * 2558 * @param quat 2559 * the {@link Quaterniond} 2560 * @param ox 2561 * the x coordinate of the rotation origin 2562 * @param oy 2563 * the y coordinate of the rotation origin 2564 * @param oz 2565 * the z coordinate of the rotation origin 2566 * @return this 2567 */ 2568 ref public Matrix4x3d rotateAround(Quaterniond quat, double ox, double oy, double oz) return { 2569 rotateAround(quat, ox, oy, oz, this); 2570 return this; 2571 } 2572 2573 private Matrix4x3d rotateAroundAffine(Quaterniond quat, double ox, double oy, double oz, ref Matrix4x3d dest) { 2574 double w2 = quat.w * quat.w, x2 = quat.x * quat.x; 2575 double y2 = quat.y * quat.y, z2 = quat.z * quat.z; 2576 double zw = quat.z * quat.w, dzw = zw + zw, xy = quat.x * quat.y, dxy = xy + xy; 2577 double xz = quat.x * quat.z, dxz = xz + xz, yw = quat.y * quat.w, dyw = yw + yw; 2578 double yz = quat.y * quat.z, dyz = yz + yz, xw = quat.x * quat.w, dxw = xw + xw; 2579 double rm00 = w2 + x2 - z2 - y2; 2580 double rm01 = dxy + dzw; 2581 double rm02 = dxz - dyw; 2582 double rm10 = dxy - dzw; 2583 double rm11 = y2 - z2 + w2 - x2; 2584 double rm12 = dyz + dxw; 2585 double rm20 = dyw + dxz; 2586 double rm21 = dyz - dxw; 2587 double rm22 = z2 - y2 - x2 + w2; 2588 double tm30 = m00 * ox + m10 * oy + m20 * oz + m30; 2589 double tm31 = m01 * ox + m11 * oy + m21 * oz + m31; 2590 double tm32 = m02 * ox + m12 * oy + m22 * oz + m32; 2591 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 2592 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 2593 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 2594 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 2595 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 2596 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 2597 dest 2598 ._m20(m00 * rm20 + m10 * rm21 + m20 * rm22) 2599 ._m21(m01 * rm20 + m11 * rm21 + m21 * rm22) 2600 ._m22(m02 * rm20 + m12 * rm21 + m22 * rm22) 2601 ._m00(nm00) 2602 ._m01(nm01) 2603 ._m02(nm02) 2604 ._m10(nm10) 2605 ._m11(nm11) 2606 ._m12(nm12) 2607 ._m30(-nm00 * ox - nm10 * oy - m20 * oz + tm30) 2608 ._m31(-nm01 * ox - nm11 * oy - m21 * oz + tm31) 2609 ._m32(-nm02 * ox - nm12 * oy - m22 * oz + tm32) 2610 ._properties(properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); 2611 return dest; 2612 } 2613 2614 public Matrix4x3d rotateAround(Quaterniond quat, double ox, double oy, double oz, ref Matrix4x3d dest) { 2615 if ((properties & PROPERTY_IDENTITY) != 0) 2616 return rotationAround(quat, ox, oy, oz); 2617 return rotateAroundAffine(quat, ox, oy, oz, dest); 2618 } 2619 2620 /** 2621 * 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. 2622 * <p> 2623 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2624 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2625 * When used with a left-handed coordinate system, the rotation is clockwise. 2626 * <p> 2627 * This method is equivalent to calling: <code>translation(ox, oy, oz).rotate(quat).translate(-ox, -oy, -oz)</code> 2628 * <p> 2629 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 2630 * 2631 * @param quat 2632 * the {@link Quaterniond} 2633 * @param ox 2634 * the x coordinate of the rotation origin 2635 * @param oy 2636 * the y coordinate of the rotation origin 2637 * @param oz 2638 * the z coordinate of the rotation origin 2639 * @return this 2640 */ 2641 ref public Matrix4x3d rotationAround(Quaterniond quat, double ox, double oy, double oz) return { 2642 double w2 = quat.w * quat.w, x2 = quat.x * quat.x; 2643 double y2 = quat.y * quat.y, z2 = quat.z * quat.z; 2644 double zw = quat.z * quat.w, dzw = zw + zw, xy = quat.x * quat.y, dxy = xy + xy; 2645 double xz = quat.x * quat.z, dxz = xz + xz, yw = quat.y * quat.w, dyw = yw + yw; 2646 double yz = quat.y * quat.z, dyz = yz + yz, xw = quat.x * quat.w, dxw = xw + xw; 2647 this._m20(dyw + dxz); 2648 this._m21(dyz - dxw); 2649 this._m22(z2 - y2 - x2 + w2); 2650 this._m00(w2 + x2 - z2 - y2); 2651 this._m01(dxy + dzw); 2652 this._m02(dxz - dyw); 2653 this._m10(dxy - dzw); 2654 this._m11(y2 - z2 + w2 - x2); 2655 this._m12(dyz + dxw); 2656 this._m30(-m00 * ox - m10 * oy - m20 * oz + ox); 2657 this._m31(-m01 * ox - m11 * oy - m21 * oz + oy); 2658 this._m32(-m02 * ox - m12 * oy - m22 * oz + oz); 2659 this.properties = PROPERTY_ORTHONORMAL; 2660 return this; 2661 } 2662 2663 /** 2664 * Pre-multiply a rotation to this matrix by rotating the given amount of radians 2665 * about the specified <code>(x, y, z)</code> axis and store the result in <code>dest</code>. 2666 * <p> 2667 * The axis described by the three components needs to be a unit vector. 2668 * <p> 2669 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2670 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2671 * When used with a left-handed coordinate system, the rotation is clockwise. 2672 * <p> 2673 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2674 * then the new matrix will be <code>R * M</code>. So when transforming a 2675 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2676 * rotation will be applied last! 2677 * <p> 2678 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2679 * transformation, use {@link #rotation(double, double, double, double) rotation()}. 2680 * <p> 2681 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2682 * 2683 * @see #rotation(double, double, double, double) 2684 * 2685 * @param ang 2686 * the angle in radians 2687 * @param x 2688 * the x component of the axis 2689 * @param y 2690 * the y component of the axis 2691 * @param z 2692 * the z component of the axis 2693 * @param dest 2694 * will hold the result 2695 * @return dest 2696 */ 2697 public Matrix4x3d rotateLocal(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2698 if (y == 0.0 && z == 0.0 && Math.absEqualsOne(x)) 2699 return rotateLocalX(x * ang, dest); 2700 else if (x == 0.0 && z == 0.0 && Math.absEqualsOne(y)) 2701 return rotateLocalY(y * ang, dest); 2702 else if (x == 0.0 && y == 0.0 && Math.absEqualsOne(z)) 2703 return rotateLocalZ(z * ang, dest); 2704 return rotateLocalInternal(ang, x, y, z, dest); 2705 } 2706 private Matrix4x3d rotateLocalInternal(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2707 double s = Math.sin(ang); 2708 double c = Math.cosFromSin(s, ang); 2709 double C = 1.0 - c; 2710 double xx = x * x, xy = x * y, xz = x * z; 2711 double yy = y * y, yz = y * z; 2712 double zz = z * z; 2713 double lm00 = xx * C + c; 2714 double lm01 = xy * C + z * s; 2715 double lm02 = xz * C - y * s; 2716 double lm10 = xy * C - z * s; 2717 double lm11 = yy * C + c; 2718 double lm12 = yz * C + x * s; 2719 double lm20 = xz * C + y * s; 2720 double lm21 = yz * C - x * s; 2721 double lm22 = zz * C + c; 2722 double nm00 = lm00 * m00 + lm10 * m01 + lm20 * m02; 2723 double nm01 = lm01 * m00 + lm11 * m01 + lm21 * m02; 2724 double nm02 = lm02 * m00 + lm12 * m01 + lm22 * m02; 2725 double nm10 = lm00 * m10 + lm10 * m11 + lm20 * m12; 2726 double nm11 = lm01 * m10 + lm11 * m11 + lm21 * m12; 2727 double nm12 = lm02 * m10 + lm12 * m11 + lm22 * m12; 2728 double nm20 = lm00 * m20 + lm10 * m21 + lm20 * m22; 2729 double nm21 = lm01 * m20 + lm11 * m21 + lm21 * m22; 2730 double nm22 = lm02 * m20 + lm12 * m21 + lm22 * m22; 2731 double nm30 = lm00 * m30 + lm10 * m31 + lm20 * m32; 2732 double nm31 = lm01 * m30 + lm11 * m31 + lm21 * m32; 2733 double nm32 = lm02 * m30 + lm12 * m31 + lm22 * m32; 2734 dest.m00 = nm00; 2735 dest.m01 = nm01; 2736 dest.m02 = nm02; 2737 dest.m10 = nm10; 2738 dest.m11 = nm11; 2739 dest.m12 = nm12; 2740 dest.m20 = nm20; 2741 dest.m21 = nm21; 2742 dest.m22 = nm22; 2743 dest.m30 = nm30; 2744 dest.m31 = nm31; 2745 dest.m32 = nm32; 2746 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2747 return dest; 2748 } 2749 2750 /** 2751 * Pre-multiply a rotation to this matrix by rotating the given amount of radians 2752 * about the specified <code>(x, y, z)</code> axis. 2753 * <p> 2754 * The axis described by the three components needs to be a unit vector. 2755 * <p> 2756 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2757 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2758 * When used with a left-handed coordinate system, the rotation is clockwise. 2759 * <p> 2760 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2761 * then the new matrix will be <code>R * M</code>. So when transforming a 2762 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2763 * rotation will be applied last! 2764 * <p> 2765 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2766 * transformation, use {@link #rotation(double, double, double, double) rotation()}. 2767 * <p> 2768 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2769 * 2770 * @see #rotation(double, double, double, double) 2771 * 2772 * @param ang 2773 * the angle in radians 2774 * @param x 2775 * the x component of the axis 2776 * @param y 2777 * the y component of the axis 2778 * @param z 2779 * the z component of the axis 2780 * @return this 2781 */ 2782 ref public Matrix4x3d rotateLocal(double ang, double x, double y, double z) return { 2783 rotateLocal(ang, x, y, z, this); 2784 return this; 2785 } 2786 2787 /** 2788 * Pre-multiply a rotation around the X axis to this matrix by rotating the given amount of radians 2789 * about the X axis and store the result in <code>dest</code>. 2790 * <p> 2791 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2792 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2793 * When used with a left-handed coordinate system, the rotation is clockwise. 2794 * <p> 2795 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2796 * then the new matrix will be <code>R * M</code>. So when transforming a 2797 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2798 * rotation will be applied last! 2799 * <p> 2800 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2801 * transformation, use {@link #rotationX(double) rotationX()}. 2802 * <p> 2803 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2804 * 2805 * @see #rotationX(double) 2806 * 2807 * @param ang 2808 * the angle in radians to rotate about the X axis 2809 * @param dest 2810 * will hold the result 2811 * @return dest 2812 */ 2813 public Matrix4x3d rotateLocalX(double ang, ref Matrix4x3d dest) { 2814 double sin = Math.sin(ang); 2815 double cos = Math.cosFromSin(sin, ang); 2816 double nm01 = cos * m01 - sin * m02; 2817 double nm02 = sin * m01 + cos * m02; 2818 double nm11 = cos * m11 - sin * m12; 2819 double nm12 = sin * m11 + cos * m12; 2820 double nm21 = cos * m21 - sin * m22; 2821 double nm22 = sin * m21 + cos * m22; 2822 double nm31 = cos * m31 - sin * m32; 2823 double nm32 = sin * m31 + cos * m32; 2824 dest.m00 = m00; 2825 dest.m01 = nm01; 2826 dest.m02 = nm02; 2827 dest.m10 = m10; 2828 dest.m11 = nm11; 2829 dest.m12 = nm12; 2830 dest.m20 = m20; 2831 dest.m21 = nm21; 2832 dest.m22 = nm22; 2833 dest.m30 = m30; 2834 dest.m31 = nm31; 2835 dest.m32 = nm32; 2836 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2837 return dest; 2838 } 2839 2840 /** 2841 * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the X axis. 2842 * <p> 2843 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2844 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2845 * When used with a left-handed coordinate system, the rotation is clockwise. 2846 * <p> 2847 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2848 * then the new matrix will be <code>R * M</code>. So when transforming a 2849 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2850 * rotation will be applied last! 2851 * <p> 2852 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2853 * transformation, use {@link #rotationX(double) rotationX()}. 2854 * <p> 2855 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2856 * 2857 * @see #rotationX(double) 2858 * 2859 * @param ang 2860 * the angle in radians to rotate about the X axis 2861 * @return this 2862 */ 2863 ref public Matrix4x3d rotateLocalX(double ang) return { 2864 rotateLocalX(ang, this); 2865 return this; 2866 } 2867 2868 /** 2869 * Pre-multiply a rotation around the Y axis to this matrix by rotating the given amount of radians 2870 * about the Y axis and store the result in <code>dest</code>. 2871 * <p> 2872 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2873 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2874 * When used with a left-handed coordinate system, the rotation is clockwise. 2875 * <p> 2876 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2877 * then the new matrix will be <code>R * M</code>. So when transforming a 2878 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2879 * rotation will be applied last! 2880 * <p> 2881 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2882 * transformation, use {@link #rotationY(double) rotationY()}. 2883 * <p> 2884 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2885 * 2886 * @see #rotationY(double) 2887 * 2888 * @param ang 2889 * the angle in radians to rotate about the Y axis 2890 * @param dest 2891 * will hold the result 2892 * @return dest 2893 */ 2894 public Matrix4x3d rotateLocalY(double ang, ref Matrix4x3d dest) { 2895 double sin = Math.sin(ang); 2896 double cos = Math.cosFromSin(sin, ang); 2897 double nm00 = cos * m00 + sin * m02; 2898 double nm02 = -sin * m00 + cos * m02; 2899 double nm10 = cos * m10 + sin * m12; 2900 double nm12 = -sin * m10 + cos * m12; 2901 double nm20 = cos * m20 + sin * m22; 2902 double nm22 = -sin * m20 + cos * m22; 2903 double nm30 = cos * m30 + sin * m32; 2904 double nm32 = -sin * m30 + cos * m32; 2905 dest.m00 = nm00; 2906 dest.m01 = m01; 2907 dest.m02 = nm02; 2908 dest.m10 = nm10; 2909 dest.m11 = m11; 2910 dest.m12 = nm12; 2911 dest.m20 = nm20; 2912 dest.m21 = m21; 2913 dest.m22 = nm22; 2914 dest.m30 = nm30; 2915 dest.m31 = m31; 2916 dest.m32 = nm32; 2917 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2918 return dest; 2919 } 2920 2921 /** 2922 * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the Y axis. 2923 * <p> 2924 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2925 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2926 * When used with a left-handed coordinate system, the rotation is clockwise. 2927 * <p> 2928 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2929 * then the new matrix will be <code>R * M</code>. So when transforming a 2930 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2931 * rotation will be applied last! 2932 * <p> 2933 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2934 * transformation, use {@link #rotationY(double) rotationY()}. 2935 * <p> 2936 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2937 * 2938 * @see #rotationY(double) 2939 * 2940 * @param ang 2941 * the angle in radians to rotate about the Y axis 2942 * @return this 2943 */ 2944 ref public Matrix4x3d rotateLocalY(double ang) return { 2945 rotateLocalY(ang, this); 2946 return this; 2947 } 2948 2949 /** 2950 * Pre-multiply a rotation around the Z axis to this matrix by rotating the given amount of radians 2951 * about the Z axis and store the result in <code>dest</code>. 2952 * <p> 2953 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2954 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2955 * When used with a left-handed coordinate system, the rotation is clockwise. 2956 * <p> 2957 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2958 * then the new matrix will be <code>R * M</code>. So when transforming a 2959 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2960 * rotation will be applied last! 2961 * <p> 2962 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2963 * transformation, use {@link #rotationZ(double) rotationZ()}. 2964 * <p> 2965 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2966 * 2967 * @see #rotationZ(double) 2968 * 2969 * @param ang 2970 * the angle in radians to rotate about the Z axis 2971 * @param dest 2972 * will hold the result 2973 * @return dest 2974 */ 2975 public Matrix4x3d rotateLocalZ(double ang, ref Matrix4x3d dest) { 2976 double sin = Math.sin(ang); 2977 double cos = Math.cosFromSin(sin, ang); 2978 double nm00 = cos * m00 - sin * m01; 2979 double nm01 = sin * m00 + cos * m01; 2980 double nm10 = cos * m10 - sin * m11; 2981 double nm11 = sin * m10 + cos * m11; 2982 double nm20 = cos * m20 - sin * m21; 2983 double nm21 = sin * m20 + cos * m21; 2984 double nm30 = cos * m30 - sin * m31; 2985 double nm31 = sin * m30 + cos * m31; 2986 dest.m00 = nm00; 2987 dest.m01 = nm01; 2988 dest.m02 = m02; 2989 dest.m10 = nm10; 2990 dest.m11 = nm11; 2991 dest.m12 = m12; 2992 dest.m20 = nm20; 2993 dest.m21 = nm21; 2994 dest.m22 = m22; 2995 dest.m30 = nm30; 2996 dest.m31 = nm31; 2997 dest.m32 = m32; 2998 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2999 return dest; 3000 } 3001 3002 /** 3003 * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the Z axis. 3004 * <p> 3005 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3006 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3007 * When used with a left-handed coordinate system, the rotation is clockwise. 3008 * <p> 3009 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3010 * then the new matrix will be <code>R * M</code>. So when transforming a 3011 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 3012 * rotation will be applied last! 3013 * <p> 3014 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 3015 * transformation, use {@link #rotationZ(double) rotationY()}. 3016 * <p> 3017 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 3018 * 3019 * @see #rotationY(double) 3020 * 3021 * @param ang 3022 * the angle in radians to rotate about the Z axis 3023 * @return this 3024 */ 3025 ref public Matrix4x3d rotateLocalZ(double ang) return { 3026 rotateLocalZ(ang, this); 3027 return this; 3028 } 3029 3030 /** 3031 * Apply a translation to this matrix by translating by the given number of 3032 * units in x, y and z. 3033 * <p> 3034 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3035 * matrix, then the new matrix will be <code>M * T</code>. So when 3036 * transforming a vector <code>v</code> with the new matrix by using 3037 * <code>M * T * v</code>, the translation will be applied first! 3038 * <p> 3039 * In order to set the matrix to a translation transformation without post-multiplying 3040 * it, use {@link #translation(Vector3d)}. 3041 * 3042 * @see #translation(Vector3d) 3043 * 3044 * @param offset 3045 * the number of units in x, y and z by which to translate 3046 * @return this 3047 */ 3048 ref public Matrix4x3d translate(Vector3d offset) return { 3049 return translate(offset.x, offset.y, offset.z); 3050 } 3051 3052 /** 3053 * Apply a translation to this matrix by translating by the given number of 3054 * units in x, y and z and store the result in <code>dest</code>. 3055 * <p> 3056 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3057 * matrix, then the new matrix will be <code>M * T</code>. So when 3058 * transforming a vector <code>v</code> with the new matrix by using 3059 * <code>M * T * v</code>, the translation will be applied first! 3060 * <p> 3061 * In order to set the matrix to a translation transformation without post-multiplying 3062 * it, use {@link #translation(Vector3d)}. 3063 * 3064 * @see #translation(Vector3d) 3065 * 3066 * @param offset 3067 * the number of units in x, y and z by which to translate 3068 * @param dest 3069 * will hold the result 3070 * @return dest 3071 */ 3072 public Matrix4x3d translate(Vector3d offset, ref Matrix4x3d dest) { 3073 return translate(offset.x, offset.y, offset.z, dest); 3074 } 3075 3076 /** 3077 * Apply a translation to this matrix by translating by the given number of 3078 * units in x, y and z and store the result in <code>dest</code>. 3079 * <p> 3080 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3081 * matrix, then the new matrix will be <code>M * T</code>. So when 3082 * transforming a vector <code>v</code> with the new matrix by using 3083 * <code>M * T * v</code>, the translation will be applied first! 3084 * <p> 3085 * In order to set the matrix to a translation transformation without post-multiplying 3086 * it, use {@link #translation(double, double, double)}. 3087 * 3088 * @see #translation(double, double, double) 3089 * 3090 * @param x 3091 * the offset to translate in x 3092 * @param y 3093 * the offset to translate in y 3094 * @param z 3095 * the offset to translate in z 3096 * @param dest 3097 * will hold the result 3098 * @return dest 3099 */ 3100 public Matrix4x3d translate(double x, double y, double z, ref Matrix4x3d dest) { 3101 if ((properties & PROPERTY_IDENTITY) != 0) 3102 return dest.translation(x, y, z); 3103 return translateGeneric(x, y, z, dest); 3104 } 3105 private Matrix4x3d translateGeneric(double x, double y, double z, ref Matrix4x3d dest) { 3106 dest.m00 = m00; 3107 dest.m01 = m01; 3108 dest.m02 = m02; 3109 dest.m10 = m10; 3110 dest.m11 = m11; 3111 dest.m12 = m12; 3112 dest.m20 = m20; 3113 dest.m21 = m21; 3114 dest.m22 = m22; 3115 dest.m30 = m00 * x + m10 * y + m20 * z + m30; 3116 dest.m31 = m01 * x + m11 * y + m21 * z + m31; 3117 dest.m32 = m02 * x + m12 * y + m22 * z + m32; 3118 dest.properties = properties & ~(PROPERTY_IDENTITY); 3119 return dest; 3120 } 3121 3122 /** 3123 * Apply a translation to this matrix by translating by the given number of 3124 * units in x, y and z. 3125 * <p> 3126 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3127 * matrix, then the new matrix will be <code>M * T</code>. So when 3128 * transforming a vector <code>v</code> with the new matrix by using 3129 * <code>M * T * v</code>, the translation will be applied first! 3130 * <p> 3131 * In order to set the matrix to a translation transformation without post-multiplying 3132 * it, use {@link #translation(double, double, double)}. 3133 * 3134 * @see #translation(double, double, double) 3135 * 3136 * @param x 3137 * the offset to translate in x 3138 * @param y 3139 * the offset to translate in y 3140 * @param z 3141 * the offset to translate in z 3142 * @return this 3143 */ 3144 ref public Matrix4x3d translate(double x, double y, double z) return { 3145 if ((properties & PROPERTY_IDENTITY) != 0) 3146 return translation(x, y, z); 3147 Matrix4x3d c = this; 3148 c.m30 = c.m00 * x + c.m10 * y + c.m20 * z + c.m30; 3149 c.m31 = c.m01 * x + c.m11 * y + c.m21 * z + c.m31; 3150 c.m32 = c.m02 * x + c.m12 * y + c.m22 * z + c.m32; 3151 c.properties &= ~(PROPERTY_IDENTITY); 3152 return this; 3153 } 3154 3155 3156 /** 3157 * Pre-multiply a translation to this matrix by translating by the given number of 3158 * units in x, y and z. 3159 * <p> 3160 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3161 * matrix, then the new matrix will be <code>T * M</code>. So when 3162 * transforming a vector <code>v</code> with the new matrix by using 3163 * <code>T * M * v</code>, the translation will be applied last! 3164 * <p> 3165 * In order to set the matrix to a translation transformation without pre-multiplying 3166 * it, use {@link #translation(Vector3d)}. 3167 * 3168 * @see #translation(Vector3d) 3169 * 3170 * @param offset 3171 * the number of units in x, y and z by which to translate 3172 * @return this 3173 */ 3174 ref public Matrix4x3d translateLocal(Vector3d offset) return { 3175 return translateLocal(offset.x, offset.y, offset.z); 3176 } 3177 3178 /** 3179 * Pre-multiply a translation to this matrix by translating by the given number of 3180 * units in x, y and z and store the result in <code>dest</code>. 3181 * <p> 3182 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3183 * matrix, then the new matrix will be <code>T * M</code>. So when 3184 * transforming a vector <code>v</code> with the new matrix by using 3185 * <code>T * M * v</code>, the translation will be applied last! 3186 * <p> 3187 * In order to set the matrix to a translation transformation without pre-multiplying 3188 * it, use {@link #translation(Vector3d)}. 3189 * 3190 * @see #translation(Vector3d) 3191 * 3192 * @param offset 3193 * the number of units in x, y and z by which to translate 3194 * @param dest 3195 * will hold the result 3196 * @return dest 3197 */ 3198 public Matrix4x3d translateLocal(Vector3d offset, ref Matrix4x3d dest) { 3199 return translateLocal(offset.x, offset.y, offset.z, dest); 3200 } 3201 3202 /** 3203 * Pre-multiply a translation to this matrix by translating by the given number of 3204 * units in x, y and z and store the result in <code>dest</code>. 3205 * <p> 3206 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3207 * matrix, then the new matrix will be <code>T * M</code>. So when 3208 * transforming a vector <code>v</code> with the new matrix by using 3209 * <code>T * M * v</code>, the translation will be applied last! 3210 * <p> 3211 * In order to set the matrix to a translation transformation without pre-multiplying 3212 * it, use {@link #translation(double, double, double)}. 3213 * 3214 * @see #translation(double, double, double) 3215 * 3216 * @param x 3217 * the offset to translate in x 3218 * @param y 3219 * the offset to translate in y 3220 * @param z 3221 * the offset to translate in z 3222 * @param dest 3223 * will hold the result 3224 * @return dest 3225 */ 3226 public Matrix4x3d translateLocal(double x, double y, double z, ref Matrix4x3d dest) { 3227 dest.m00 = m00; 3228 dest.m01 = m01; 3229 dest.m02 = m02; 3230 dest.m10 = m10; 3231 dest.m11 = m11; 3232 dest.m12 = m12; 3233 dest.m20 = m20; 3234 dest.m21 = m21; 3235 dest.m22 = m22; 3236 dest.m30 = m30 + x; 3237 dest.m31 = m31 + y; 3238 dest.m32 = m32 + z; 3239 dest.properties = properties & ~(PROPERTY_IDENTITY); 3240 return dest; 3241 } 3242 3243 /** 3244 * Pre-multiply a translation to this matrix by translating by the given number of 3245 * units in x, y and z. 3246 * <p> 3247 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3248 * matrix, then the new matrix will be <code>T * M</code>. So when 3249 * transforming a vector <code>v</code> with the new matrix by using 3250 * <code>T * M * v</code>, the translation will be applied last! 3251 * <p> 3252 * In order to set the matrix to a translation transformation without pre-multiplying 3253 * it, use {@link #translation(double, double, double)}. 3254 * 3255 * @see #translation(double, double, double) 3256 * 3257 * @param x 3258 * the offset to translate in x 3259 * @param y 3260 * the offset to translate in y 3261 * @param z 3262 * the offset to translate in z 3263 * @return this 3264 */ 3265 ref public Matrix4x3d translateLocal(double x, double y, double z) return { 3266 translateLocal(x, y, z, this); 3267 return this; 3268 } 3269 3270 public Matrix4x3d rotateX(double ang, ref Matrix4x3d dest) { 3271 if ((properties & PROPERTY_IDENTITY) != 0) 3272 return dest.rotationX(ang); 3273 else if ((properties & PROPERTY_TRANSLATION) != 0) { 3274 double x = m30, y = m31, z = m32; 3275 return dest.rotationX(ang).setTranslation(x, y, z); 3276 } 3277 return rotateXInternal(ang, dest); 3278 } 3279 private Matrix4x3d rotateXInternal(double ang, ref Matrix4x3d dest) { 3280 double sin, cos; 3281 sin = Math.sin(ang); 3282 cos = Math.cosFromSin(sin, ang); 3283 double rm11 = cos; 3284 double rm12 = sin; 3285 double rm21 = -sin; 3286 double rm22 = cos; 3287 3288 // add temporaries for dependent values 3289 double nm10 = m10 * rm11 + m20 * rm12; 3290 double nm11 = m11 * rm11 + m21 * rm12; 3291 double nm12 = m12 * rm11 + m22 * rm12; 3292 // set non-dependent values directly 3293 dest.m20 = m10 * rm21 + m20 * rm22; 3294 dest.m21 = m11 * rm21 + m21 * rm22; 3295 dest.m22 = m12 * rm21 + m22 * rm22; 3296 // set other values 3297 dest.m10 = nm10; 3298 dest.m11 = nm11; 3299 dest.m12 = nm12; 3300 dest.m00 = m00; 3301 dest.m01 = m01; 3302 dest.m02 = m02; 3303 dest.m30 = m30; 3304 dest.m31 = m31; 3305 dest.m32 = m32; 3306 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3307 return dest; 3308 } 3309 3310 /** 3311 * Apply rotation about the X axis to this matrix by rotating the given amount of radians. 3312 * <p> 3313 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3314 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3315 * When used with a left-handed coordinate system, the rotation is clockwise. 3316 * <p> 3317 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3318 * then the new matrix will be <code>M * R</code>. So when transforming a 3319 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3320 * rotation will be applied first! 3321 * <p> 3322 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 3323 * 3324 * @param ang 3325 * the angle in radians 3326 * @return this 3327 */ 3328 ref public Matrix4x3d rotateX(double ang) return { 3329 rotateX(ang, this); 3330 return this; 3331 } 3332 3333 public Matrix4x3d rotateY(double ang, ref Matrix4x3d dest) { 3334 if ((properties & PROPERTY_IDENTITY) != 0) 3335 return dest.rotationY(ang); 3336 else if ((properties & PROPERTY_TRANSLATION) != 0) { 3337 double x = m30, y = m31, z = m32; 3338 return dest.rotationY(ang).setTranslation(x, y, z); 3339 } 3340 return rotateYInternal(ang, dest); 3341 } 3342 private Matrix4x3d rotateYInternal(double ang, ref Matrix4x3d dest) { 3343 double sin, cos; 3344 sin = Math.sin(ang); 3345 cos = Math.cosFromSin(sin, ang); 3346 double rm00 = cos; 3347 double rm02 = -sin; 3348 double rm20 = sin; 3349 double rm22 = cos; 3350 3351 // add temporaries for dependent values 3352 double nm00 = m00 * rm00 + m20 * rm02; 3353 double nm01 = m01 * rm00 + m21 * rm02; 3354 double nm02 = m02 * rm00 + m22 * rm02; 3355 // set non-dependent values directly 3356 dest.m20 = m00 * rm20 + m20 * rm22; 3357 dest.m21 = m01 * rm20 + m21 * rm22; 3358 dest.m22 = m02 * rm20 + m22 * rm22; 3359 // set other values 3360 dest.m00 = nm00; 3361 dest.m01 = nm01; 3362 dest.m02 = nm02; 3363 dest.m10 = m10; 3364 dest.m11 = m11; 3365 dest.m12 = m12; 3366 dest.m30 = m30; 3367 dest.m31 = m31; 3368 dest.m32 = m32; 3369 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3370 return dest; 3371 } 3372 3373 /** 3374 * Apply rotation about the Y axis to this matrix by rotating the given amount of radians. 3375 * <p> 3376 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3377 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3378 * When used with a left-handed coordinate system, the rotation is clockwise. 3379 * <p> 3380 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3381 * then the new matrix will be <code>M * R</code>. So when transforming a 3382 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3383 * rotation will be applied first! 3384 * <p> 3385 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 3386 * 3387 * @param ang 3388 * the angle in radians 3389 * @return this 3390 */ 3391 ref public Matrix4x3d rotateY(double ang) return { 3392 rotateY(ang, this); 3393 return this; 3394 } 3395 3396 public Matrix4x3d rotateZ(double ang, ref Matrix4x3d dest) { 3397 if ((properties & PROPERTY_IDENTITY) != 0) 3398 return dest.rotationZ(ang); 3399 else if ((properties & PROPERTY_TRANSLATION) != 0) { 3400 double x = m30, y = m31, z = m32; 3401 return dest.rotationZ(ang).setTranslation(x, y, z); 3402 } 3403 return rotateZInternal(ang, dest); 3404 } 3405 private Matrix4x3d rotateZInternal(double ang, ref Matrix4x3d dest) { 3406 double sin, cos; 3407 sin = Math.sin(ang); 3408 cos = Math.cosFromSin(sin, ang); 3409 double rm00 = cos; 3410 double rm01 = sin; 3411 double rm10 = -sin; 3412 double rm11 = cos; 3413 3414 // add temporaries for dependent values 3415 double nm00 = m00 * rm00 + m10 * rm01; 3416 double nm01 = m01 * rm00 + m11 * rm01; 3417 double nm02 = m02 * rm00 + m12 * rm01; 3418 // set non-dependent values directly 3419 dest.m10 = m00 * rm10 + m10 * rm11; 3420 dest.m11 = m01 * rm10 + m11 * rm11; 3421 dest.m12 = m02 * rm10 + m12 * rm11; 3422 // set other values 3423 dest.m00 = nm00; 3424 dest.m01 = nm01; 3425 dest.m02 = nm02; 3426 dest.m20 = m20; 3427 dest.m21 = m21; 3428 dest.m22 = m22; 3429 dest.m30 = m30; 3430 dest.m31 = m31; 3431 dest.m32 = m32; 3432 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3433 return dest; 3434 } 3435 3436 /** 3437 * Apply rotation about the Z axis to this matrix by rotating the given amount of radians. 3438 * <p> 3439 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3440 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3441 * When used with a left-handed coordinate system, the rotation is clockwise. 3442 * <p> 3443 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3444 * then the new matrix will be <code>M * R</code>. So when transforming a 3445 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3446 * rotation will be applied first! 3447 * <p> 3448 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 3449 * 3450 * @param ang 3451 * the angle in radians 3452 * @return this 3453 */ 3454 ref public Matrix4x3d rotateZ(double ang) return { 3455 rotateZ(ang, this); 3456 return this; 3457 } 3458 3459 /** 3460 * 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 3461 * followed by a rotation of <code>angles.z</code> radians about the Z axis. 3462 * <p> 3463 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3464 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3465 * When used with a left-handed coordinate system, the rotation is clockwise. 3466 * <p> 3467 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3468 * then the new matrix will be <code>M * R</code>. So when transforming a 3469 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3470 * rotation will be applied first! 3471 * <p> 3472 * This method is equivalent to calling: <code>rotateX(angles.x).rotateY(angles.y).rotateZ(angles.z)</code> 3473 * 3474 * @param angles 3475 * the Euler angles 3476 * @return this 3477 */ 3478 ref public Matrix4x3d rotateXYZ(Vector3d angles) return { 3479 return rotateXYZ(angles.x, angles.y, angles.z); 3480 } 3481 3482 /** 3483 * 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 3484 * followed by a rotation of <code>angleZ</code> radians about the Z axis. 3485 * <p> 3486 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3487 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3488 * When used with a left-handed coordinate system, the rotation is clockwise. 3489 * <p> 3490 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3491 * then the new matrix will be <code>M * R</code>. So when transforming a 3492 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3493 * rotation will be applied first! 3494 * <p> 3495 * This method is equivalent to calling: <code>rotateX(angleX).rotateY(angleY).rotateZ(angleZ)</code> 3496 * 3497 * @param angleX 3498 * the angle to rotate about X 3499 * @param angleY 3500 * the angle to rotate about Y 3501 * @param angleZ 3502 * the angle to rotate about Z 3503 * @return this 3504 */ 3505 ref public Matrix4x3d rotateXYZ(double angleX, double angleY, double angleZ) return { 3506 rotateXYZ(angleX, angleY, angleZ, this); 3507 return this; 3508 } 3509 3510 public Matrix4x3d rotateXYZ(double angleX, double angleY, double angleZ, ref Matrix4x3d dest) { 3511 if ((properties & PROPERTY_IDENTITY) != 0) 3512 return dest.rotationXYZ(angleX, angleY, angleZ); 3513 else if ((properties & PROPERTY_TRANSLATION) != 0) { 3514 double tx = m30, ty = m31, tz = m32; 3515 return dest.rotationXYZ(angleX, angleY, angleZ).setTranslation(tx, ty, tz); 3516 } 3517 return rotateXYZInternal(angleX, angleY, angleZ, dest); 3518 } 3519 private Matrix4x3d rotateXYZInternal(double angleX, double angleY, double angleZ, ref Matrix4x3d dest) { 3520 double sinX = Math.sin(angleX); 3521 double cosX = Math.cosFromSin(sinX, angleX); 3522 double sinY = Math.sin(angleY); 3523 double cosY = Math.cosFromSin(sinY, angleY); 3524 double sinZ = Math.sin(angleZ); 3525 double cosZ = Math.cosFromSin(sinZ, angleZ); 3526 double m_sinX = -sinX; 3527 double m_sinY = -sinY; 3528 double m_sinZ = -sinZ; 3529 3530 // rotateX 3531 double nm10 = m10 * cosX + m20 * sinX; 3532 double nm11 = m11 * cosX + m21 * sinX; 3533 double nm12 = m12 * cosX + m22 * sinX; 3534 double nm20 = m10 * m_sinX + m20 * cosX; 3535 double nm21 = m11 * m_sinX + m21 * cosX; 3536 double nm22 = m12 * m_sinX + m22 * cosX; 3537 // rotateY 3538 double nm00 = m00 * cosY + nm20 * m_sinY; 3539 double nm01 = m01 * cosY + nm21 * m_sinY; 3540 double nm02 = m02 * cosY + nm22 * m_sinY; 3541 dest.m20 = m00 * sinY + nm20 * cosY; 3542 dest.m21 = m01 * sinY + nm21 * cosY; 3543 dest.m22 = m02 * sinY + nm22 * cosY; 3544 // rotateZ 3545 dest.m00 = nm00 * cosZ + nm10 * sinZ; 3546 dest.m01 = nm01 * cosZ + nm11 * sinZ; 3547 dest.m02 = nm02 * cosZ + nm12 * sinZ; 3548 dest.m10 = nm00 * m_sinZ + nm10 * cosZ; 3549 dest.m11 = nm01 * m_sinZ + nm11 * cosZ; 3550 dest.m12 = nm02 * m_sinZ + nm12 * cosZ; 3551 // copy last column from 'this' 3552 dest.m30 = m30; 3553 dest.m31 = m31; 3554 dest.m32 = m32; 3555 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3556 return dest; 3557 } 3558 3559 /** 3560 * 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 3561 * followed by a rotation of <code>angles.x</code> radians about the X axis. 3562 * <p> 3563 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3564 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3565 * When used with a left-handed coordinate system, the rotation is clockwise. 3566 * <p> 3567 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3568 * then the new matrix will be <code>M * R</code>. So when transforming a 3569 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3570 * rotation will be applied first! 3571 * <p> 3572 * This method is equivalent to calling: <code>rotateZ(angles.z).rotateY(angles.y).rotateX(angles.x)</code> 3573 * 3574 * @param angles 3575 * the Euler angles 3576 * @return this 3577 */ 3578 ref public Matrix4x3d rotateZYX(Vector3d angles) return { 3579 return rotateZYX(angles.z, angles.y, angles.x); 3580 } 3581 3582 /** 3583 * 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 3584 * followed by a rotation of <code>angleX</code> radians about the X axis. 3585 * <p> 3586 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3587 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3588 * When used with a left-handed coordinate system, the rotation is clockwise. 3589 * <p> 3590 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3591 * then the new matrix will be <code>M * R</code>. So when transforming a 3592 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3593 * rotation will be applied first! 3594 * <p> 3595 * This method is equivalent to calling: <code>rotateZ(angleZ).rotateY(angleY).rotateX(angleX)</code> 3596 * 3597 * @param angleZ 3598 * the angle to rotate about Z 3599 * @param angleY 3600 * the angle to rotate about Y 3601 * @param angleX 3602 * the angle to rotate about X 3603 * @return this 3604 */ 3605 ref public Matrix4x3d rotateZYX(double angleZ, double angleY, double angleX) return { 3606 rotateZYX(angleZ, angleY, angleX, this); 3607 return this; 3608 } 3609 3610 public Matrix4x3d rotateZYX(double angleZ, double angleY, double angleX, ref Matrix4x3d dest) { 3611 if ((properties & PROPERTY_IDENTITY) != 0) 3612 return dest.rotationZYX(angleZ, angleY, angleX); 3613 else if ((properties & PROPERTY_TRANSLATION) != 0) { 3614 double tx = m30, ty = m31, tz = m32; 3615 return dest.rotationZYX(angleZ, angleY, angleX).setTranslation(tx, ty, tz); 3616 } 3617 return rotateZYXInternal(angleZ, angleY, angleX, dest); 3618 } 3619 private Matrix4x3d rotateZYXInternal(double angleZ, double angleY, double angleX, ref Matrix4x3d dest) { 3620 double sinX = Math.sin(angleX); 3621 double cosX = Math.cosFromSin(sinX, angleX); 3622 double sinY = Math.sin(angleY); 3623 double cosY = Math.cosFromSin(sinY, angleY); 3624 double sinZ = Math.sin(angleZ); 3625 double cosZ = Math.cosFromSin(sinZ, angleZ); 3626 double m_sinZ = -sinZ; 3627 double m_sinY = -sinY; 3628 double m_sinX = -sinX; 3629 3630 // rotateZ 3631 double nm00 = m00 * cosZ + m10 * sinZ; 3632 double nm01 = m01 * cosZ + m11 * sinZ; 3633 double nm02 = m02 * cosZ + m12 * sinZ; 3634 double nm10 = m00 * m_sinZ + m10 * cosZ; 3635 double nm11 = m01 * m_sinZ + m11 * cosZ; 3636 double nm12 = m02 * m_sinZ + m12 * cosZ; 3637 // rotateY 3638 double nm20 = nm00 * sinY + m20 * cosY; 3639 double nm21 = nm01 * sinY + m21 * cosY; 3640 double nm22 = nm02 * sinY + m22 * cosY; 3641 dest.m00 = nm00 * cosY + m20 * m_sinY; 3642 dest.m01 = nm01 * cosY + m21 * m_sinY; 3643 dest.m02 = nm02 * cosY + m22 * m_sinY; 3644 // rotateX 3645 dest.m10 = nm10 * cosX + nm20 * sinX; 3646 dest.m11 = nm11 * cosX + nm21 * sinX; 3647 dest.m12 = nm12 * cosX + nm22 * sinX; 3648 dest.m20 = nm10 * m_sinX + nm20 * cosX; 3649 dest.m21 = nm11 * m_sinX + nm21 * cosX; 3650 dest.m22 = nm12 * m_sinX + nm22 * cosX; 3651 // copy last column from 'this' 3652 dest.m30 = m30; 3653 dest.m31 = m31; 3654 dest.m32 = m32; 3655 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3656 return dest; 3657 } 3658 3659 /** 3660 * 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 3661 * followed by a rotation of <code>angles.z</code> radians about the Z axis. 3662 * <p> 3663 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3664 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3665 * When used with a left-handed coordinate system, the rotation is clockwise. 3666 * <p> 3667 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3668 * then the new matrix will be <code>M * R</code>. So when transforming a 3669 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3670 * rotation will be applied first! 3671 * <p> 3672 * This method is equivalent to calling: <code>rotateY(angles.y).rotateX(angles.x).rotateZ(angles.z)</code> 3673 * 3674 * @param angles 3675 * the Euler angles 3676 * @return this 3677 */ 3678 ref public Matrix4x3d rotateYXZ(Vector3d angles) return { 3679 return rotateYXZ(angles.y, angles.x, angles.z); 3680 } 3681 3682 /** 3683 * 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 3684 * followed by a rotation of <code>angleZ</code> radians about the Z axis. 3685 * <p> 3686 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3687 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3688 * When used with a left-handed coordinate system, the rotation is clockwise. 3689 * <p> 3690 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3691 * then the new matrix will be <code>M * R</code>. So when transforming a 3692 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3693 * rotation will be applied first! 3694 * <p> 3695 * This method is equivalent to calling: <code>rotateY(angleY).rotateX(angleX).rotateZ(angleZ)</code> 3696 * 3697 * @param angleY 3698 * the angle to rotate about Y 3699 * @param angleX 3700 * the angle to rotate about X 3701 * @param angleZ 3702 * the angle to rotate about Z 3703 * @return this 3704 */ 3705 ref public Matrix4x3d rotateYXZ(double angleY, double angleX, double angleZ) return { 3706 rotateYXZ(angleY, angleX, angleZ, this); 3707 return this; 3708 } 3709 3710 public Matrix4x3d rotateYXZ(double angleY, double angleX, double angleZ, ref Matrix4x3d dest) { 3711 if ((properties & PROPERTY_IDENTITY) != 0) 3712 return dest.rotationYXZ(angleY, angleX, angleZ); 3713 else if ((properties & PROPERTY_TRANSLATION) != 0) { 3714 double tx = m30, ty = m31, tz = m32; 3715 return dest.rotationYXZ(angleY, angleX, angleZ).setTranslation(tx, ty, tz); 3716 } 3717 return rotateYXZInternal(angleY, angleX, angleZ, dest); 3718 } 3719 private Matrix4x3d rotateYXZInternal(double angleY, double angleX, double angleZ, ref Matrix4x3d dest) { 3720 double sinX = Math.sin(angleX); 3721 double cosX = Math.cosFromSin(sinX, angleX); 3722 double sinY = Math.sin(angleY); 3723 double cosY = Math.cosFromSin(sinY, angleY); 3724 double sinZ = Math.sin(angleZ); 3725 double cosZ = Math.cosFromSin(sinZ, angleZ); 3726 double m_sinY = -sinY; 3727 double m_sinX = -sinX; 3728 double m_sinZ = -sinZ; 3729 3730 // rotateY 3731 double nm20 = m00 * sinY + m20 * cosY; 3732 double nm21 = m01 * sinY + m21 * cosY; 3733 double nm22 = m02 * sinY + m22 * cosY; 3734 double nm00 = m00 * cosY + m20 * m_sinY; 3735 double nm01 = m01 * cosY + m21 * m_sinY; 3736 double nm02 = m02 * cosY + m22 * m_sinY; 3737 // rotateX 3738 double nm10 = m10 * cosX + nm20 * sinX; 3739 double nm11 = m11 * cosX + nm21 * sinX; 3740 double nm12 = m12 * cosX + nm22 * sinX; 3741 dest.m20 = m10 * m_sinX + nm20 * cosX; 3742 dest.m21 = m11 * m_sinX + nm21 * cosX; 3743 dest.m22 = m12 * m_sinX + nm22 * cosX; 3744 // rotateZ 3745 dest.m00 = nm00 * cosZ + nm10 * sinZ; 3746 dest.m01 = nm01 * cosZ + nm11 * sinZ; 3747 dest.m02 = nm02 * cosZ + nm12 * sinZ; 3748 dest.m10 = nm00 * m_sinZ + nm10 * cosZ; 3749 dest.m11 = nm01 * m_sinZ + nm11 * cosZ; 3750 dest.m12 = nm02 * m_sinZ + nm12 * cosZ; 3751 // copy last column from 'this' 3752 dest.m30 = m30; 3753 dest.m31 = m31; 3754 dest.m32 = m32; 3755 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3756 return dest; 3757 } 3758 3759 3760 /** 3761 * Set this matrix to a rotation transformation using the given {@link AxisAngle4d}. 3762 * <p> 3763 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3764 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3765 * When used with a left-handed coordinate system, the rotation is clockwise. 3766 * <p> 3767 * The resulting matrix can be multiplied against another transformation 3768 * matrix to obtain an additional rotation. 3769 * <p> 3770 * In order to apply the rotation transformation to an existing transformation, 3771 * use {@link #rotate(AxisAngle4d) rotate()} instead. 3772 * <p> 3773 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 3774 * 3775 * @see #rotate(AxisAngle4d) 3776 * 3777 * @param angleAxis 3778 * the {@link AxisAngle4d} (needs to be {@link AxisAngle4d#normalize() normalized}) 3779 * @return this 3780 */ 3781 ref public Matrix4x3d rotation(AxisAngle4d angleAxis) return { 3782 return rotation(angleAxis.angle, angleAxis.x, angleAxis.y, angleAxis.z); 3783 } 3784 3785 /** 3786 * Set this matrix to the rotation - and possibly scaling - transformation of the given {@link Quaterniond}. 3787 * <p> 3788 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3789 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3790 * When used with a left-handed coordinate system, the rotation is clockwise. 3791 * <p> 3792 * The resulting matrix can be multiplied against another transformation 3793 * matrix to obtain an additional rotation. 3794 * <p> 3795 * In order to apply the rotation transformation to an existing transformation, 3796 * use {@link #rotate(Quaterniond) rotate()} instead. 3797 * <p> 3798 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 3799 * 3800 * @see #rotate(Quaterniond) 3801 * 3802 * @param quat 3803 * the {@link Quaterniond} 3804 * @return this 3805 */ 3806 ref public Matrix4x3d rotation(Quaterniond quat) return { 3807 double w2 = quat.w * quat.w; 3808 double x2 = quat.x * quat.x; 3809 double y2 = quat.y * quat.y; 3810 double z2 = quat.z * quat.z; 3811 double zw = quat.z * quat.w, dzw = zw + zw; 3812 double xy = quat.x * quat.y, dxy = xy + xy; 3813 double xz = quat.x * quat.z, dxz = xz + xz; 3814 double yw = quat.y * quat.w, dyw = yw + yw; 3815 double yz = quat.y * quat.z, dyz = yz + yz; 3816 double xw = quat.x * quat.w, dxw = xw + xw; 3817 _m00(w2 + x2 - z2 - y2); 3818 _m01(dxy + dzw); 3819 _m02(dxz - dyw); 3820 _m10(dxy - dzw); 3821 _m11(y2 - z2 + w2 - x2); 3822 _m12(dyz + dxw); 3823 _m20(dyw + dxz); 3824 _m21(dyz - dxw); 3825 _m22(z2 - y2 - x2 + w2); 3826 _m30(0.0); 3827 _m31(0.0); 3828 _m32(0.0); 3829 properties = PROPERTY_ORTHONORMAL; 3830 return this; 3831 } 3832 3833 3834 /** 3835 * 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>, 3836 * <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 3837 * which scales the three axes x, y and z by <code>(sx, sy, sz)</code>. 3838 * <p> 3839 * When transforming a vector by the resulting matrix the scaling transformation will be applied first, then the rotation and 3840 * at last the translation. 3841 * <p> 3842 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3843 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3844 * When used with a left-handed coordinate system, the rotation is clockwise. 3845 * <p> 3846 * This method is equivalent to calling: <code>translation(tx, ty, tz).rotate(quat).scale(sx, sy, sz)</code> 3847 * 3848 * @see #translation(double, double, double) 3849 * @see #rotate(Quaterniond) 3850 * @see #scale(double, double, double) 3851 * 3852 * @param tx 3853 * the number of units by which to translate the x-component 3854 * @param ty 3855 * the number of units by which to translate the y-component 3856 * @param tz 3857 * the number of units by which to translate the z-component 3858 * @param qx 3859 * the x-coordinate of the vector part of the quaternion 3860 * @param qy 3861 * the y-coordinate of the vector part of the quaternion 3862 * @param qz 3863 * the z-coordinate of the vector part of the quaternion 3864 * @param qw 3865 * the scalar part of the quaternion 3866 * @param sx 3867 * the scaling factor for the x-axis 3868 * @param sy 3869 * the scaling factor for the y-axis 3870 * @param sz 3871 * the scaling factor for the z-axis 3872 * @return this 3873 */ 3874 ref public Matrix4x3d translationRotateScale(double tx, double ty, double tz, 3875 double qx, double qy, double qz, double qw, 3876 double sx, double sy, double sz) return { 3877 double dqx = qx + qx, dqy = qy + qy, dqz = qz + qz; 3878 double q00 = dqx * qx; 3879 double q11 = dqy * qy; 3880 double q22 = dqz * qz; 3881 double q01 = dqx * qy; 3882 double q02 = dqx * qz; 3883 double q03 = dqx * qw; 3884 double q12 = dqy * qz; 3885 double q13 = dqy * qw; 3886 double q23 = dqz * qw; 3887 m00 = sx - (q11 + q22) * sx; 3888 m01 = (q01 + q23) * sx; 3889 m02 = (q02 - q13) * sx; 3890 m10 = (q01 - q23) * sy; 3891 m11 = sy - (q22 + q00) * sy; 3892 m12 = (q12 + q03) * sy; 3893 m20 = (q02 + q13) * sz; 3894 m21 = (q12 - q03) * sz; 3895 m22 = sz - (q11 + q00) * sz; 3896 m30 = tx; 3897 m31 = ty; 3898 m32 = tz; 3899 properties = 0; 3900 return this; 3901 } 3902 3903 /** 3904 * Set <code>this</code> matrix to <code>T * R * S</code>, where <code>T</code> is the given <code>translation</code>, 3905 * <code>R</code> is a rotation transformation specified by the given quaternion, and <code>S</code> is a scaling transformation 3906 * which scales the axes by <code>scale</code>. 3907 * <p> 3908 * When transforming a vector by the resulting matrix the scaling transformation will be applied first, then the rotation and 3909 * at last the translation. 3910 * <p> 3911 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3912 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3913 * When used with a left-handed coordinate system, the rotation is clockwise. 3914 * <p> 3915 * This method is equivalent to calling: <code>translation(translation).rotate(quat).scale(scale)</code> 3916 * 3917 * @see #translation(Vector3d) 3918 * @see #rotate(Quaterniond) 3919 * 3920 * @param translation 3921 * the translation 3922 * @param quat 3923 * the quaternion representing a rotation 3924 * @param scale 3925 * the scaling factors 3926 * @return this 3927 */ 3928 ref public Matrix4x3d translationRotateScale(Vector3d translation, 3929 Quaterniond quat, 3930 Vector3d scale) return { 3931 return translationRotateScale(translation.x, translation.y, translation.z, quat.x, quat.y, quat.z, 3932 quat.w, scale.x, scale.y, scale.z); 3933 } 3934 3935 /** 3936 * 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>, 3937 * <code>R</code> is a rotation transformation specified by the quaternion <code>(qx, qy, qz, qw)</code>, <code>S</code> is a scaling transformation 3938 * which scales the three axes x, y and z by <code>(sx, sy, sz)</code>. 3939 * <p> 3940 * 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 3941 * at last the translation. 3942 * <p> 3943 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3944 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3945 * When used with a left-handed coordinate system, the rotation is clockwise. 3946 * <p> 3947 * This method is equivalent to calling: <code>translation(tx, ty, tz).rotate(quat).scale(sx, sy, sz).mul(m)</code> 3948 * 3949 * @see #translation(double, double, double) 3950 * @see #rotate(Quaterniond) 3951 * @see #scale(double, double, double) 3952 * @see #mul(Matrix4x3d) 3953 * 3954 * @param tx 3955 * the number of units by which to translate the x-component 3956 * @param ty 3957 * the number of units by which to translate the y-component 3958 * @param tz 3959 * the number of units by which to translate the z-component 3960 * @param qx 3961 * the x-coordinate of the vector part of the quaternion 3962 * @param qy 3963 * the y-coordinate of the vector part of the quaternion 3964 * @param qz 3965 * the z-coordinate of the vector part of the quaternion 3966 * @param qw 3967 * the scalar part of the quaternion 3968 * @param sx 3969 * the scaling factor for the x-axis 3970 * @param sy 3971 * the scaling factor for the y-axis 3972 * @param sz 3973 * the scaling factor for the z-axis 3974 * @param m 3975 * the matrix to multiply by 3976 * @return this 3977 */ 3978 ref public Matrix4x3d translationRotateScaleMul( 3979 double tx, double ty, double tz, 3980 double qx, double qy, double qz, double qw, 3981 double sx, double sy, double sz, 3982 Matrix4x3d m) return { 3983 double dqx = qx + qx; 3984 double dqy = qy + qy; 3985 double dqz = qz + qz; 3986 double q00 = dqx * qx; 3987 double q11 = dqy * qy; 3988 double q22 = dqz * qz; 3989 double q01 = dqx * qy; 3990 double q02 = dqx * qz; 3991 double q03 = dqx * qw; 3992 double q12 = dqy * qz; 3993 double q13 = dqy * qw; 3994 double q23 = dqz * qw; 3995 double nm00 = sx - (q11 + q22) * sx; 3996 double nm01 = (q01 + q23) * sx; 3997 double nm02 = (q02 - q13) * sx; 3998 double nm10 = (q01 - q23) * sy; 3999 double nm11 = sy - (q22 + q00) * sy; 4000 double nm12 = (q12 + q03) * sy; 4001 double nm20 = (q02 + q13) * sz; 4002 double nm21 = (q12 - q03) * sz; 4003 double nm22 = sz - (q11 + q00) * sz; 4004 double __m00 = nm00 * m.m00 + nm10 * m.m01 + nm20 * m.m02; 4005 double __m01 = nm01 * m.m00 + nm11 * m.m01 + nm21 * m.m02; 4006 m02 = nm02 * m.m00 + nm12 * m.m01 + nm22 * m.m02; 4007 this.m00 = __m00; 4008 this.m01 = __m01; 4009 double __m10 = nm00 * m.m10 + nm10 * m.m11 + nm20 * m.m12; 4010 double __m11 = nm01 * m.m10 + nm11 * m.m11 + nm21 * m.m12; 4011 m12 = nm02 * m.m10 + nm12 * m.m11 + nm22 * m.m12; 4012 this.m10 = __m10; 4013 this.m11 = __m11; 4014 double __m20 = nm00 * m.m20 + nm10 * m.m21 + nm20 * m.m22; 4015 double __m21 = nm01 * m.m20 + nm11 * m.m21 + nm21 * m.m22; 4016 m22 = nm02 * m.m20 + nm12 * m.m21 + nm22 * m.m22; 4017 this.m20 = __m20; 4018 this.m21 = __m21; 4019 double __m30 = nm00 * m.m30 + nm10 * m.m31 + nm20 * m.m32 + tx; 4020 double __m31 = nm01 * m.m30 + nm11 * m.m31 + nm21 * m.m32 + ty; 4021 m32 = nm02 * m.m30 + nm12 * m.m31 + nm22 * m.m32 + tz; 4022 this.m30 = __m30; 4023 this.m31 = __m31; 4024 properties = 0; 4025 return this; 4026 } 4027 4028 /** 4029 * Set <code>this</code> matrix to <code>T * R * S * M</code>, where <code>T</code> is the given <code>translation</code>, 4030 * <code>R</code> is a rotation transformation specified by the given quaternion, <code>S</code> is a scaling transformation 4031 * which scales the axes by <code>scale</code>. 4032 * <p> 4033 * 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 4034 * at last the translation. 4035 * <p> 4036 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4037 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4038 * When used with a left-handed coordinate system, the rotation is clockwise. 4039 * <p> 4040 * This method is equivalent to calling: <code>translation(translation).rotate(quat).scale(scale).mul(m)</code> 4041 * 4042 * @see #translation(Vector3d) 4043 * @see #rotate(Quaterniond) 4044 * @see #mul(Matrix4x3d) 4045 * 4046 * @param translation 4047 * the translation 4048 * @param quat 4049 * the quaternion representing a rotation 4050 * @param scale 4051 * the scaling factors 4052 * @param m 4053 * the matrix to multiply by 4054 * @return this 4055 */ 4056 ref public Matrix4x3d translationRotateScaleMul(Vector3d translation, Quaterniond quat, Vector3d scale, Matrix4x3d m) return { 4057 return translationRotateScaleMul(translation.x, translation.y, translation.z, quat.x, quat.y, quat.z 4058 , quat.w, scale.x, scale.y, scale.z, m); 4059 } 4060 4061 /** 4062 * 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 4063 * <code>R</code> is a rotation transformation specified by the given quaternion. 4064 * <p> 4065 * When transforming a vector by the resulting matrix the rotation transformation will be applied first and then the translation. 4066 * <p> 4067 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4068 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4069 * When used with a left-handed coordinate system, the rotation is clockwise. 4070 * <p> 4071 * This method is equivalent to calling: <code>translation(tx, ty, tz).rotate(quat)</code> 4072 * 4073 * @see #translation(double, double, double) 4074 * @see #rotate(Quaterniond) 4075 * 4076 * @param tx 4077 * the number of units by which to translate the x-component 4078 * @param ty 4079 * the number of units by which to translate the y-component 4080 * @param tz 4081 * the number of units by which to translate the z-component 4082 * @param quat 4083 * the quaternion representing a rotation 4084 * @return this 4085 */ 4086 ref public Matrix4x3d translationRotate(double tx, double ty, double tz, Quaterniond quat) return { 4087 double dqx = quat.x + quat.x, dqy = quat.y + quat.y, dqz = quat.z + quat.z; 4088 double q00 = dqx * quat.x; 4089 double q11 = dqy * quat.y; 4090 double q22 = dqz * quat.z; 4091 double q01 = dqx * quat.y; 4092 double q02 = dqx * quat.z; 4093 double q03 = dqx * quat.w; 4094 double q12 = dqy * quat.z; 4095 double q13 = dqy * quat.w; 4096 double q23 = dqz * quat.w; 4097 m00 = 1.0 - (q11 + q22); 4098 m01 = q01 + q23; 4099 m02 = q02 - q13; 4100 m10 = q01 - q23; 4101 m11 = 1.0 - (q22 + q00); 4102 m12 = q12 + q03; 4103 m20 = q02 + q13; 4104 m21 = q12 - q03; 4105 m22 = 1.0 - (q11 + q00); 4106 m30 = tx; 4107 m31 = ty; 4108 m32 = tz; 4109 properties = PROPERTY_ORTHONORMAL; 4110 return this; 4111 } 4112 4113 /** 4114 * 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 4115 * <code>R</code> is a rotation - and possibly scaling - transformation specified by the quaternion <code>(qx, qy, qz, qw)</code>. 4116 * <p> 4117 * When transforming a vector by the resulting matrix the rotation - and possibly scaling - transformation will be applied first and then the translation. 4118 * <p> 4119 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4120 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4121 * When used with a left-handed coordinate system, the rotation is clockwise. 4122 * <p> 4123 * This method is equivalent to calling: <code>translation(tx, ty, tz).rotate(quat)</code> 4124 * 4125 * @see #translation(double, double, double) 4126 * @see #rotate(Quaterniond) 4127 * 4128 * @param tx 4129 * the number of units by which to translate the x-component 4130 * @param ty 4131 * the number of units by which to translate the y-component 4132 * @param tz 4133 * the number of units by which to translate the z-component 4134 * @param qx 4135 * the x-coordinate of the vector part of the quaternion 4136 * @param qy 4137 * the y-coordinate of the vector part of the quaternion 4138 * @param qz 4139 * the z-coordinate of the vector part of the quaternion 4140 * @param qw 4141 * the scalar part of the quaternion 4142 * @return this 4143 */ 4144 ref public Matrix4x3d translationRotate(double tx, double ty, double tz, double qx, double qy, double qz, double qw) return { 4145 double w2 = qw * qw; 4146 double x2 = qx * qx; 4147 double y2 = qy * qy; 4148 double z2 = qz * qz; 4149 double zw = qz * qw; 4150 double xy = qx * qy; 4151 double xz = qx * qz; 4152 double yw = qy * qw; 4153 double yz = qy * qz; 4154 double xw = qx * qw; 4155 this.m00 = w2 + x2 - z2 - y2; 4156 this.m01 = xy + zw + zw + xy; 4157 this.m02 = xz - yw + xz - yw; 4158 this.m10 = -zw + xy - zw + xy; 4159 this.m11 = y2 - z2 + w2 - x2; 4160 this.m12 = yz + yz + xw + xw; 4161 this.m20 = yw + xz + xz + yw; 4162 this.m21 = yz + yz - xw - xw; 4163 this.m22 = z2 - y2 - x2 + w2; 4164 this.m30 = tx; 4165 this.m31 = ty; 4166 this.m32 = tz; 4167 this.properties = PROPERTY_ORTHONORMAL; 4168 return this; 4169 } 4170 4171 /** 4172 * Set <code>this</code> matrix to <code>T * R</code>, where <code>T</code> is the given <code>translation</code> and 4173 * <code>R</code> is a rotation transformation specified by the given quaternion. 4174 * <p> 4175 * When transforming a vector by the resulting matrix the scaling transformation will be applied first, then the rotation and 4176 * at last the translation. 4177 * <p> 4178 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4179 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4180 * When used with a left-handed coordinate system, the rotation is clockwise. 4181 * <p> 4182 * This method is equivalent to calling: <code>translation(translation).rotate(quat)</code> 4183 * 4184 * @see #translation(Vector3d) 4185 * @see #rotate(Quaterniond) 4186 * 4187 * @param translation 4188 * the translation 4189 * @param quat 4190 * the quaternion representing a rotation 4191 * @return this 4192 */ 4193 ref public Matrix4x3d translationRotate(Vector3d translation, 4194 Quaterniond quat) return { 4195 return translationRotate(translation.x, translation.y, translation.z, quat.x, quat.y, quat.z, quat.w); 4196 } 4197 4198 /** 4199 * 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>, 4200 * <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> 4201 * <p> 4202 * 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 4203 * at last the translation. 4204 * <p> 4205 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4206 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4207 * When used with a left-handed coordinate system, the rotation is clockwise. 4208 * <p> 4209 * This method is equivalent to calling: <code>translation(tx, ty, tz).rotate(quat).mul(mat)</code> 4210 * 4211 * @see #translation(double, double, double) 4212 * @see #rotate(Quaternionfc) 4213 * @see #mul(Matrix4x3d) 4214 * 4215 * @param tx 4216 * the number of units by which to translate the x-component 4217 * @param ty 4218 * the number of units by which to translate the y-component 4219 * @param tz 4220 * the number of units by which to translate the z-component 4221 * @param qx 4222 * the x-coordinate of the vector part of the quaternion 4223 * @param qy 4224 * the y-coordinate of the vector part of the quaternion 4225 * @param qz 4226 * the z-coordinate of the vector part of the quaternion 4227 * @param qw 4228 * the scalar part of the quaternion 4229 * @param mat 4230 * the matrix to multiply with 4231 * @return this 4232 */ 4233 ref public Matrix4x3d translationRotateMul(double tx, double ty, double tz, double qx, double qy, double qz, double qw, Matrix4x3d mat) return { 4234 double w2 = qw * qw; 4235 double x2 = qx * qx; 4236 double y2 = qy * qy; 4237 double z2 = qz * qz; 4238 double zw = qz * qw; 4239 double xy = qx * qy; 4240 double xz = qx * qz; 4241 double yw = qy * qw; 4242 double yz = qy * qz; 4243 double xw = qx * qw; 4244 double nm00 = w2 + x2 - z2 - y2; 4245 double nm01 = xy + zw + zw + xy; 4246 double nm02 = xz - yw + xz - yw; 4247 double nm10 = -zw + xy - zw + xy; 4248 double nm11 = y2 - z2 + w2 - x2; 4249 double nm12 = yz + yz + xw + xw; 4250 double nm20 = yw + xz + xz + yw; 4251 double nm21 = yz + yz - xw - xw; 4252 double nm22 = z2 - y2 - x2 + w2; 4253 m00 = nm00 * mat.m00 + nm10 * mat.m01 + nm20 * mat.m02; 4254 m01 = nm01 * mat.m00 + nm11 * mat.m01 + nm21 * mat.m02; 4255 m02 = nm02 * mat.m00 + nm12 * mat.m01 + nm22 * mat.m02; 4256 m10 = nm00 * mat.m10 + nm10 * mat.m11 + nm20 * mat.m12; 4257 m11 = nm01 * mat.m10 + nm11 * mat.m11 + nm21 * mat.m12; 4258 m12 = nm02 * mat.m10 + nm12 * mat.m11 + nm22 * mat.m12; 4259 m20 = nm00 * mat.m20 + nm10 * mat.m21 + nm20 * mat.m22; 4260 m21 = nm01 * mat.m20 + nm11 * mat.m21 + nm21 * mat.m22; 4261 m22 = nm02 * mat.m20 + nm12 * mat.m21 + nm22 * mat.m22; 4262 m30 = nm00 * mat.m30 + nm10 * mat.m31 + nm20 * mat.m32 + tx; 4263 m31 = nm01 * mat.m30 + nm11 * mat.m31 + nm21 * mat.m32 + ty; 4264 m32 = nm02 * mat.m30 + nm12 * mat.m31 + nm22 * mat.m32 + tz; 4265 this.properties = 0; 4266 return this; 4267 } 4268 4269 /** 4270 * 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 4271 * <code>R</code> is a rotation transformation specified by the quaternion <code>(qx, qy, qz, qw)</code>. 4272 * <p> 4273 * This method is equivalent to calling: <code>translationRotate(...).invert()</code> 4274 * 4275 * @see #translationRotate(double, double, double, double, double, double, double) 4276 * @see #invert() 4277 * 4278 * @param tx 4279 * the number of units by which to translate the x-component 4280 * @param ty 4281 * the number of units by which to translate the y-component 4282 * @param tz 4283 * the number of units by which to translate the z-component 4284 * @param qx 4285 * the x-coordinate of the vector part of the quaternion 4286 * @param qy 4287 * the y-coordinate of the vector part of the quaternion 4288 * @param qz 4289 * the z-coordinate of the vector part of the quaternion 4290 * @param qw 4291 * the scalar part of the quaternion 4292 * @return this 4293 */ 4294 ref public Matrix4x3d translationRotateInvert(double tx, double ty, double tz, double qx, double qy, double qz, 4295 double qw) return { 4296 double nqx = -qx, nqy = -qy, nqz = -qz; 4297 double dqx = nqx + nqx; 4298 double dqy = nqy + nqy; 4299 double dqz = nqz + nqz; 4300 double q00 = dqx * nqx; 4301 double q11 = dqy * nqy; 4302 double q22 = dqz * nqz; 4303 double q01 = dqx * nqy; 4304 double q02 = dqx * nqz; 4305 double q03 = dqx * qw; 4306 double q12 = dqy * nqz; 4307 double q13 = dqy * qw; 4308 double q23 = dqz * qw; 4309 return this 4310 ._m00(1.0 - q11 - q22) 4311 ._m01(q01 + q23) 4312 ._m02(q02 - q13) 4313 ._m10(q01 - q23) 4314 ._m11(1.0 - q22 - q00) 4315 ._m12(q12 + q03) 4316 ._m20(q02 + q13) 4317 ._m21(q12 - q03) 4318 ._m22(1.0 - q11 - q00) 4319 ._m30(-m00 * tx - m10 * ty - m20 * tz) 4320 ._m31(-m01 * tx - m11 * ty - m21 * tz) 4321 ._m32(-m02 * tx - m12 * ty - m22 * tz) 4322 ._properties(PROPERTY_ORTHONORMAL); 4323 } 4324 4325 /** 4326 * Set <code>this</code> matrix to <code>(T * R)<sup>-1</sup></code>, where <code>T</code> is the given <code>translation</code> and 4327 * <code>R</code> is a rotation transformation specified by the given quaternion. 4328 * <p> 4329 * This method is equivalent to calling: <code>translationRotate(...).invert()</code> 4330 * 4331 * @see #translationRotate(Vector3d, Quaterniond) 4332 * @see #invert() 4333 * 4334 * @param translation 4335 * the translation 4336 * @param quat 4337 * the quaternion representing a rotation 4338 * @return this 4339 */ 4340 ref public Matrix4x3d translationRotateInvert(Vector3d translation, 4341 Quaterniond quat) return { 4342 return translationRotateInvert(translation.x, translation.y, translation.z, quat.x, quat.y, quat.z, 4343 quat.w); 4344 } 4345 4346 /** 4347 * Apply the rotation - and possibly scaling - transformation of the given {@link Quaterniond} to this matrix and store 4348 * the result in <code>dest</code>. 4349 * <p> 4350 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4351 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4352 * When used with a left-handed coordinate system, the rotation is clockwise. 4353 * <p> 4354 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 4355 * then the new matrix will be <code>M * Q</code>. So when transforming a 4356 * vector <code>v</code> with the new matrix by using <code>M * Q * v</code>, 4357 * the quaternion rotation will be applied first! 4358 * <p> 4359 * In order to set the matrix to a rotation transformation without post-multiplying, 4360 * use {@link #rotation(Quaterniond)}. 4361 * <p> 4362 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 4363 * 4364 * @see #rotation(Quaterniond) 4365 * 4366 * @param quat 4367 * the {@link Quaterniond} 4368 * @param dest 4369 * will hold the result 4370 * @return dest 4371 */ 4372 public Matrix4x3d rotate(Quaterniond quat, ref Matrix4x3d dest) { 4373 if ((properties & PROPERTY_IDENTITY) != 0) 4374 return dest.rotation(quat); 4375 else if ((properties & PROPERTY_TRANSLATION) != 0) 4376 return rotateTranslation(quat, dest); 4377 return rotateGeneric(quat, dest); 4378 } 4379 private Matrix4x3d rotateGeneric(Quaterniond quat, ref Matrix4x3d dest) { 4380 double w2 = quat.w * quat.w, x2 = quat.x * quat.x; 4381 double y2 = quat.y * quat.y, z2 = quat.z * quat.z; 4382 double zw = quat.z * quat.w, dzw = zw + zw, xy = quat.x * quat.y, dxy = xy + xy; 4383 double xz = quat.x * quat.z, dxz = xz + xz, yw = quat.y * quat.w, dyw = yw + yw; 4384 double yz = quat.y * quat.z, dyz = yz + yz, xw = quat.x * quat.w, dxw = xw + xw; 4385 double rm00 = w2 + x2 - z2 - y2; 4386 double rm01 = dxy + dzw; 4387 double rm02 = dxz - dyw; 4388 double rm10 = dxy - dzw; 4389 double rm11 = y2 - z2 + w2 - x2; 4390 double rm12 = dyz + dxw; 4391 double rm20 = dyw + dxz; 4392 double rm21 = dyz - dxw; 4393 double rm22 = z2 - y2 - x2 + w2; 4394 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 4395 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 4396 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 4397 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 4398 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 4399 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 4400 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 4401 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 4402 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 4403 dest.m00 = nm00; 4404 dest.m01 = nm01; 4405 dest.m02 = nm02; 4406 dest.m10 = nm10; 4407 dest.m11 = nm11; 4408 dest.m12 = nm12; 4409 dest.m30 = m30; 4410 dest.m31 = m31; 4411 dest.m32 = m32; 4412 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 4413 return dest; 4414 } 4415 4416 4417 /** 4418 * Apply the rotation - and possibly scaling - transformation of the given {@link Quaterniond} to this matrix. 4419 * <p> 4420 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4421 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4422 * When used with a left-handed coordinate system, the rotation is clockwise. 4423 * <p> 4424 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 4425 * then the new matrix will be <code>M * Q</code>. So when transforming a 4426 * vector <code>v</code> with the new matrix by using <code>M * Q * v</code>, 4427 * the quaternion rotation will be applied first! 4428 * <p> 4429 * In order to set the matrix to a rotation transformation without post-multiplying, 4430 * use {@link #rotation(Quaterniond)}. 4431 * <p> 4432 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 4433 * 4434 * @see #rotation(Quaterniond) 4435 * 4436 * @param quat 4437 * the {@link Quaterniond} 4438 * @return this 4439 */ 4440 ref public Matrix4x3d rotate(Quaterniond quat) return { 4441 rotate(quat, this); 4442 return this; 4443 } 4444 4445 4446 /** 4447 * 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 4448 * the result in <code>dest</code>. 4449 * <p> 4450 * This method assumes <code>this</code> to only contain a translation. 4451 * <p> 4452 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4453 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4454 * When used with a left-handed coordinate system, the rotation is clockwise. 4455 * <p> 4456 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 4457 * then the new matrix will be <code>M * Q</code>. So when transforming a 4458 * vector <code>v</code> with the new matrix by using <code>M * Q * v</code>, 4459 * the quaternion rotation will be applied first! 4460 * <p> 4461 * In order to set the matrix to a rotation transformation without post-multiplying, 4462 * use {@link #rotation(Quaterniond)}. 4463 * <p> 4464 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 4465 * 4466 * @see #rotation(Quaterniond) 4467 * 4468 * @param quat 4469 * the {@link Quaterniond} 4470 * @param dest 4471 * will hold the result 4472 * @return dest 4473 */ 4474 public Matrix4x3d rotateTranslation(Quaterniond quat, ref Matrix4x3d dest) { 4475 double w2 = quat.w * quat.w, x2 = quat.x * quat.x; 4476 double y2 = quat.y * quat.y, z2 = quat.z * quat.z; 4477 double zw = quat.z * quat.w, dzw = zw + zw, xy = quat.x * quat.y, dxy = xy + xy; 4478 double xz = quat.x * quat.z, dxz = xz + xz, yw = quat.y * quat.w, dyw = yw + yw; 4479 double yz = quat.y * quat.z, dyz = yz + yz, xw = quat.x * quat.w, dxw = xw + xw; 4480 double rm00 = w2 + x2 - z2 - y2; 4481 double rm01 = dxy + dzw; 4482 double rm02 = dxz - dyw; 4483 double rm10 = dxy - dzw; 4484 double rm11 = y2 - z2 + w2 - x2; 4485 double rm12 = dyz + dxw; 4486 double rm20 = dyw + dxz; 4487 double rm21 = dyz - dxw; 4488 double rm22 = z2 - y2 - x2 + w2; 4489 dest.m20 = rm20; 4490 dest.m21 = rm21; 4491 dest.m22 = rm22; 4492 dest.m00 = rm00; 4493 dest.m01 = rm01; 4494 dest.m02 = rm02; 4495 dest.m10 = rm10; 4496 dest.m11 = rm11; 4497 dest.m12 = rm12; 4498 dest.m30 = m30; 4499 dest.m31 = m31; 4500 dest.m32 = m32; 4501 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 4502 return dest; 4503 } 4504 4505 4506 /** 4507 * Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaterniond} to this matrix and store 4508 * the result in <code>dest</code>. 4509 * <p> 4510 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4511 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4512 * When used with a left-handed coordinate system, the rotation is clockwise. 4513 * <p> 4514 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 4515 * then the new matrix will be <code>Q * M</code>. So when transforming a 4516 * vector <code>v</code> with the new matrix by using <code>Q * M * v</code>, 4517 * the quaternion rotation will be applied last! 4518 * <p> 4519 * In order to set the matrix to a rotation transformation without pre-multiplying, 4520 * use {@link #rotation(Quaterniond)}. 4521 * <p> 4522 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 4523 * 4524 * @see #rotation(Quaterniond) 4525 * 4526 * @param quat 4527 * the {@link Quaterniond} 4528 * @param dest 4529 * will hold the result 4530 * @return dest 4531 */ 4532 public Matrix4x3d rotateLocal(Quaterniond quat, ref Matrix4x3d dest) { 4533 double w2 = quat.w * quat.w, x2 = quat.x * quat.x; 4534 double y2 = quat.y * quat.y, z2 = quat.z * quat.z; 4535 double zw = quat.z * quat.w, dzw = zw + zw, xy = quat.x * quat.y, dxy = xy + xy; 4536 double xz = quat.x * quat.z, dxz = xz + xz, yw = quat.y * quat.w, dyw = yw + yw; 4537 double yz = quat.y * quat.z, dyz = yz + yz, xw = quat.x * quat.w, dxw = xw + xw; 4538 double lm00 = w2 + x2 - z2 - y2; 4539 double lm01 = dxy + dzw; 4540 double lm02 = dxz - dyw; 4541 double lm10 = dxy - dzw; 4542 double lm11 = y2 - z2 + w2 - x2; 4543 double lm12 = dyz + dxw; 4544 double lm20 = dyw + dxz; 4545 double lm21 = dyz - dxw; 4546 double lm22 = z2 - y2 - x2 + w2; 4547 double nm00 = lm00 * m00 + lm10 * m01 + lm20 * m02; 4548 double nm01 = lm01 * m00 + lm11 * m01 + lm21 * m02; 4549 double nm02 = lm02 * m00 + lm12 * m01 + lm22 * m02; 4550 double nm10 = lm00 * m10 + lm10 * m11 + lm20 * m12; 4551 double nm11 = lm01 * m10 + lm11 * m11 + lm21 * m12; 4552 double nm12 = lm02 * m10 + lm12 * m11 + lm22 * m12; 4553 double nm20 = lm00 * m20 + lm10 * m21 + lm20 * m22; 4554 double nm21 = lm01 * m20 + lm11 * m21 + lm21 * m22; 4555 double nm22 = lm02 * m20 + lm12 * m21 + lm22 * m22; 4556 double nm30 = lm00 * m30 + lm10 * m31 + lm20 * m32; 4557 double nm31 = lm01 * m30 + lm11 * m31 + lm21 * m32; 4558 double nm32 = lm02 * m30 + lm12 * m31 + lm22 * m32; 4559 dest.m00 = nm00; 4560 dest.m01 = nm01; 4561 dest.m02 = nm02; 4562 dest.m10 = nm10; 4563 dest.m11 = nm11; 4564 dest.m12 = nm12; 4565 dest.m20 = nm20; 4566 dest.m21 = nm21; 4567 dest.m22 = nm22; 4568 dest.m30 = nm30; 4569 dest.m31 = nm31; 4570 dest.m32 = nm32; 4571 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 4572 return dest; 4573 } 4574 4575 /** 4576 * Pre-multiply the rotation transformation of the given {@link Quaterniond} to this matrix. 4577 * <p> 4578 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4579 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4580 * When used with a left-handed coordinate system, the rotation is clockwise. 4581 * <p> 4582 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 4583 * then the new matrix will be <code>Q * M</code>. So when transforming a 4584 * vector <code>v</code> with the new matrix by using <code>Q * M * v</code>, 4585 * the quaternion rotation will be applied last! 4586 * <p> 4587 * In order to set the matrix to a rotation transformation without pre-multiplying, 4588 * use {@link #rotation(Quaterniond)}. 4589 * <p> 4590 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 4591 * 4592 * @see #rotation(Quaterniond) 4593 * 4594 * @param quat 4595 * the {@link Quaterniond} 4596 * @return this 4597 */ 4598 ref public Matrix4x3d rotateLocal(Quaterniond quat) return { 4599 rotateLocal(quat, this); 4600 return this; 4601 } 4602 4603 /** 4604 * Apply a rotation transformation, rotating about the given {@link AxisAngle4d}, to this matrix. 4605 * <p> 4606 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4607 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4608 * When used with a left-handed coordinate system, the rotation is clockwise. 4609 * <p> 4610 * If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given {@link AxisAngle4d}, 4611 * then the new matrix will be <code>M * A</code>. So when transforming a 4612 * vector <code>v</code> with the new matrix by using <code>M * A * v</code>, 4613 * the {@link AxisAngle4d} rotation will be applied first! 4614 * <p> 4615 * In order to set the matrix to a rotation transformation without post-multiplying, 4616 * use {@link #rotation(AxisAngle4d)}. 4617 * <p> 4618 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 4619 * 4620 * @see #rotate(double, double, double, double) 4621 * @see #rotation(AxisAngle4d) 4622 * 4623 * @param axisAngle 4624 * the {@link AxisAngle4d} (needs to be {@link AxisAngle4d#normalize() normalized}) 4625 * @return this 4626 */ 4627 ref public Matrix4x3d rotate(AxisAngle4d axisAngle) return { 4628 return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z); 4629 } 4630 4631 /** 4632 * Apply a rotation transformation, rotating about the given {@link AxisAngle4d} and store the result in <code>dest</code>. 4633 * <p> 4634 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4635 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4636 * When used with a left-handed coordinate system, the rotation is clockwise. 4637 * <p> 4638 * If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given {@link AxisAngle4d}, 4639 * then the new matrix will be <code>M * A</code>. So when transforming a 4640 * vector <code>v</code> with the new matrix by using <code>M * A * v</code>, 4641 * the {@link AxisAngle4d} rotation will be applied first! 4642 * <p> 4643 * In order to set the matrix to a rotation transformation without post-multiplying, 4644 * use {@link #rotation(AxisAngle4d)}. 4645 * <p> 4646 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 4647 * 4648 * @see #rotate(double, double, double, double) 4649 * @see #rotation(AxisAngle4d) 4650 * 4651 * @param axisAngle 4652 * the {@link AxisAngle4d} (needs to be {@link AxisAngle4d#normalize() normalized}) 4653 * @param dest 4654 * will hold the result 4655 * @return dest 4656 */ 4657 public Matrix4x3d rotate(AxisAngle4d axisAngle, ref Matrix4x3d dest) { 4658 return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z, dest); 4659 } 4660 4661 /** 4662 * Apply a rotation transformation, rotating the given radians about the specified axis, to this matrix. 4663 * <p> 4664 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4665 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4666 * When used with a left-handed coordinate system, the rotation is clockwise. 4667 * <p> 4668 * If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given angle and axis, 4669 * then the new matrix will be <code>M * A</code>. So when transforming a 4670 * vector <code>v</code> with the new matrix by using <code>M * A * v</code>, 4671 * the axis-angle rotation will be applied first! 4672 * <p> 4673 * In order to set the matrix to a rotation transformation without post-multiplying, 4674 * use {@link #rotation(double, Vector3d)}. 4675 * <p> 4676 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 4677 * 4678 * @see #rotate(double, double, double, double) 4679 * @see #rotation(double, Vector3d) 4680 * 4681 * @param angle 4682 * the angle in radians 4683 * @param axis 4684 * the rotation axis (needs to be {@link Vector3d#normalize() normalized}) 4685 * @return this 4686 */ 4687 ref public Matrix4x3d rotate(double angle, Vector3d axis) return { 4688 return rotate(angle, axis.x, axis.y, axis.z); 4689 } 4690 4691 /** 4692 * Apply a rotation transformation, rotating the given radians about the specified axis and store the result in <code>dest</code>. 4693 * <p> 4694 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4695 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4696 * When used with a left-handed coordinate system, the rotation is clockwise. 4697 * <p> 4698 * If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given angle and axis, 4699 * then the new matrix will be <code>M * A</code>. So when transforming a 4700 * vector <code>v</code> with the new matrix by using <code>M * A * v</code>, 4701 * the axis-angle rotation will be applied first! 4702 * <p> 4703 * In order to set the matrix to a rotation transformation without post-multiplying, 4704 * use {@link #rotation(double, Vector3d)}. 4705 * <p> 4706 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 4707 * 4708 * @see #rotate(double, double, double, double) 4709 * @see #rotation(double, Vector3d) 4710 * 4711 * @param angle 4712 * the angle in radians 4713 * @param axis 4714 * the rotation axis (needs to be {@link Vector3d#normalize() normalized}) 4715 * @param dest 4716 * will hold the result 4717 * @return dest 4718 */ 4719 public Matrix4x3d rotate(double angle, Vector3d axis, ref Matrix4x3d dest) { 4720 return rotate(angle, axis.x, axis.y, axis.z, dest); 4721 } 4722 4723 4724 public Vector4d getRow(int row, Vector4d dest) { 4725 switch (row) { 4726 case 0: 4727 dest.x = m00; 4728 dest.y = m10; 4729 dest.z = m20; 4730 dest.w = m30; 4731 break; 4732 case 1: 4733 dest.x = m01; 4734 dest.y = m11; 4735 dest.z = m21; 4736 dest.w = m31; 4737 break; 4738 case 2: 4739 dest.x = m02; 4740 dest.y = m12; 4741 dest.z = m22; 4742 dest.w = m32; 4743 break; 4744 default: {} 4745 } 4746 return dest; 4747 } 4748 4749 /** 4750 * Set the row at the given <code>row</code> index, starting with <code>0</code>. 4751 * 4752 * @param row 4753 * the row index in <code>[0..2]</code> 4754 * @param src 4755 * the row components to set 4756 * @return this 4757 * @throws IndexOutOfBoundsException if <code>row</code> is not in <code>[0..2]</code> 4758 */ 4759 ref public Matrix4x3d setRow(int row, Vector4d src) return { 4760 switch (row) { 4761 case 0: 4762 this.m00 = src.x; 4763 this.m10 = src.y; 4764 this.m20 = src.z; 4765 this.m30 = src.w; 4766 break; 4767 case 1: 4768 this.m01 = src.x; 4769 this.m11 = src.y; 4770 this.m21 = src.z; 4771 this.m31 = src.w; 4772 break; 4773 case 2: 4774 this.m02 = src.x; 4775 this.m12 = src.y; 4776 this.m22 = src.z; 4777 this.m32 = src.w; 4778 break; 4779 default: {} 4780 } 4781 properties = 0; 4782 return this; 4783 } 4784 4785 public Vector3d getColumn(int column, ref Vector3d dest) { 4786 switch (column) { 4787 case 0: 4788 dest.x = m00; 4789 dest.y = m01; 4790 dest.z = m02; 4791 break; 4792 case 1: 4793 dest.x = m10; 4794 dest.y = m11; 4795 dest.z = m12; 4796 break; 4797 case 2: 4798 dest.x = m20; 4799 dest.y = m21; 4800 dest.z = m22; 4801 break; 4802 case 3: 4803 dest.x = m30; 4804 dest.y = m31; 4805 dest.z = m32; 4806 break; 4807 default: {} 4808 } 4809 return dest; 4810 } 4811 4812 /** 4813 * Set the column at the given <code>column</code> index, starting with <code>0</code>. 4814 * 4815 * @param column 4816 * the column index in <code>[0..3]</code> 4817 * @param src 4818 * the column components to set 4819 * @return this 4820 * @throws IndexOutOfBoundsException if <code>column</code> is not in <code>[0..3]</code> 4821 */ 4822 ref public Matrix4x3d setColumn(int column, Vector3d src) return { 4823 switch (column) { 4824 case 0: 4825 this.m00 = src.x; 4826 this.m01 = src.y; 4827 this.m02 = src.z; 4828 break; 4829 case 1: 4830 this.m10 = src.x; 4831 this.m11 = src.y; 4832 this.m12 = src.z; 4833 break; 4834 case 2: 4835 this.m20 = src.x; 4836 this.m21 = src.y; 4837 this.m22 = src.z; 4838 break; 4839 case 3: 4840 this.m30 = src.x; 4841 this.m31 = src.y; 4842 this.m32 = src.z; 4843 break; 4844 default: {} 4845 } 4846 properties = 0; 4847 return this; 4848 } 4849 4850 /** 4851 * Compute a normal matrix from the left 3x3 submatrix of <code>this</code> 4852 * and store it into the left 3x3 submatrix of <code>this</code>. 4853 * All other values of <code>this</code> will be set to {@link #identity() identity}. 4854 * <p> 4855 * The normal matrix of <code>m</code> is the transpose of the inverse of <code>m</code>. 4856 * <p> 4857 * Please note that, if <code>this</code> is an orthogonal matrix or a matrix whose columns are orthogonal vectors, 4858 * then this method <i>need not</i> be invoked, since in that case <code>this</code> itself is its normal matrix. 4859 * In that case, use {@link #set3x3(Matrix4x3d)} to set a given Matrix4x3d to only the left 3x3 submatrix 4860 * of this matrix. 4861 * 4862 * @see #set3x3(Matrix4x3d) 4863 * 4864 * @return this 4865 */ 4866 ref public Matrix4x3d normal() return { 4867 normal(this); 4868 return this; 4869 } 4870 4871 /** 4872 * Compute a normal matrix from the left 3x3 submatrix of <code>this</code> 4873 * and store it into the left 3x3 submatrix of <code>dest</code>. 4874 * All other values of <code>dest</code> will be set to {@link #identity() identity}. 4875 * <p> 4876 * The normal matrix of <code>m</code> is the transpose of the inverse of <code>m</code>. 4877 * <p> 4878 * Please note that, if <code>this</code> is an orthogonal matrix or a matrix whose columns are orthogonal vectors, 4879 * then this method <i>need not</i> be invoked, since in that case <code>this</code> itself is its normal matrix. 4880 * In that case, use {@link #set3x3(Matrix4x3d)} to set a given Matrix4x3d to only the left 3x3 submatrix 4881 * of a given matrix. 4882 * 4883 * @see #set3x3(Matrix4x3d) 4884 * 4885 * @param dest 4886 * will hold the result 4887 * @return dest 4888 */ 4889 public Matrix4x3d normal(ref Matrix4x3d dest) { 4890 if ((properties & PROPERTY_IDENTITY) != 0) 4891 return dest.identity(); 4892 else if ((properties & PROPERTY_ORTHONORMAL) != 0) 4893 return normalOrthonormal(dest); 4894 return normalGeneric(dest); 4895 } 4896 private Matrix4x3d normalOrthonormal(ref Matrix4x3d dest) { 4897 if (dest != this) 4898 dest.set(this); 4899 return dest._properties(PROPERTY_ORTHONORMAL); 4900 } 4901 private Matrix4x3d normalGeneric(ref Matrix4x3d dest) { 4902 double m00m11 = m00 * m11; 4903 double m01m10 = m01 * m10; 4904 double m02m10 = m02 * m10; 4905 double m00m12 = m00 * m12; 4906 double m01m12 = m01 * m12; 4907 double m02m11 = m02 * m11; 4908 double det = (m00m11 - m01m10) * m22 + (m02m10 - m00m12) * m21 + (m01m12 - m02m11) * m20; 4909 double s = 1.0 / det; 4910 /* Invert and transpose in one go */ 4911 double nm00 = (m11 * m22 - m21 * m12) * s; 4912 double nm01 = (m20 * m12 - m10 * m22) * s; 4913 double nm02 = (m10 * m21 - m20 * m11) * s; 4914 double nm10 = (m21 * m02 - m01 * m22) * s; 4915 double nm11 = (m00 * m22 - m20 * m02) * s; 4916 double nm12 = (m20 * m01 - m00 * m21) * s; 4917 double nm20 = (m01m12 - m02m11) * s; 4918 double nm21 = (m02m10 - m00m12) * s; 4919 double nm22 = (m00m11 - m01m10) * s; 4920 dest.m00 = nm00; 4921 dest.m01 = nm01; 4922 dest.m02 = nm02; 4923 dest.m10 = nm10; 4924 dest.m11 = nm11; 4925 dest.m12 = nm12; 4926 dest.m20 = nm20; 4927 dest.m21 = nm21; 4928 dest.m22 = nm22; 4929 dest.m30 = 0.0; 4930 dest.m31 = 0.0; 4931 dest.m32 = 0.0; 4932 dest.properties = properties & ~PROPERTY_TRANSLATION; 4933 return dest; 4934 } 4935 4936 public Matrix3d normal(Matrix3d dest) { 4937 if ((properties & PROPERTY_ORTHONORMAL) != 0) 4938 return normalOrthonormal(dest); 4939 return normalGeneric(dest); 4940 } 4941 private Matrix3d normalOrthonormal(Matrix3d dest) { 4942 return dest.set(this); 4943 } 4944 private Matrix3d normalGeneric(Matrix3d dest) { 4945 double m00m11 = m00 * m11; 4946 double m01m10 = m01 * m10; 4947 double m02m10 = m02 * m10; 4948 double m00m12 = m00 * m12; 4949 double m01m12 = m01 * m12; 4950 double m02m11 = m02 * m11; 4951 double det = (m00m11 - m01m10) * m22 + (m02m10 - m00m12) * m21 + (m01m12 - m02m11) * m20; 4952 double s = 1.0 / det; 4953 /* Invert and transpose in one go */ 4954 dest.m00 = ((m11 * m22 - m21 * m12) * s); 4955 dest.m01 = ((m20 * m12 - m10 * m22) * s); 4956 dest.m02 = ((m10 * m21 - m20 * m11) * s); 4957 dest.m10 = ((m21 * m02 - m01 * m22) * s); 4958 dest.m11 = ((m00 * m22 - m20 * m02) * s); 4959 dest.m12 = ((m20 * m01 - m00 * m21) * s); 4960 dest.m20 = ((m01m12 - m02m11) * s); 4961 dest.m21 = ((m02m10 - m00m12) * s); 4962 dest.m22 = ((m00m11 - m01m10) * s); 4963 return dest; 4964 } 4965 4966 /** 4967 * Compute the cofactor matrix of the left 3x3 submatrix of <code>this</code>. 4968 * <p> 4969 * The cofactor matrix can be used instead of {@link #normal()} to transform normals 4970 * when the orientation of the normals with respect to the surface should be preserved. 4971 * 4972 * @return this 4973 */ 4974 ref public Matrix4x3d cofactor3x3() return { 4975 cofactor3x3(this); 4976 return this; 4977 } 4978 4979 /** 4980 * Compute the cofactor matrix of the left 3x3 submatrix of <code>this</code> 4981 * and store it into <code>dest</code>. 4982 * <p> 4983 * The cofactor matrix can be used instead of {@link #normal(Matrix3d)} to transform normals 4984 * when the orientation of the normals with respect to the surface should be preserved. 4985 * 4986 * @param dest 4987 * will hold the result 4988 * @return dest 4989 */ 4990 public Matrix3d cofactor3x3(Matrix3d dest) { 4991 dest.m00 = m11 * m22 - m21 * m12; 4992 dest.m01 = m20 * m12 - m10 * m22; 4993 dest.m02 = m10 * m21 - m20 * m11; 4994 dest.m10 = m21 * m02 - m01 * m22; 4995 dest.m11 = m00 * m22 - m20 * m02; 4996 dest.m12 = m20 * m01 - m00 * m21; 4997 dest.m20 = m01 * m12 - m02 * m11; 4998 dest.m21 = m02 * m10 - m00 * m12; 4999 dest.m22 = m00 * m11 - m01 * m10; 5000 return dest; 5001 } 5002 5003 /** 5004 * Compute the cofactor matrix of the left 3x3 submatrix of <code>this</code> 5005 * and store it into <code>dest</code>. 5006 * All other values of <code>dest</code> will be set to {@link #identity() identity}. 5007 * <p> 5008 * The cofactor matrix can be used instead of {@link #normal(Matrix4x3d)} to transform normals 5009 * when the orientation of the normals with respect to the surface should be preserved. 5010 * 5011 * @param dest 5012 * will hold the result 5013 * @return dest 5014 */ 5015 public Matrix4x3d cofactor3x3(ref Matrix4x3d dest) { 5016 double nm00 = m11 * m22 - m21 * m12; 5017 double nm01 = m20 * m12 - m10 * m22; 5018 double nm02 = m10 * m21 - m20 * m11; 5019 double nm10 = m21 * m02 - m01 * m22; 5020 double nm11 = m00 * m22 - m20 * m02; 5021 double nm12 = m20 * m01 - m00 * m21; 5022 double nm20 = m01 * m12 - m11 * m02; 5023 double nm21 = m02 * m10 - m12 * m00; 5024 double nm22 = m00 * m11 - m10 * m01; 5025 dest.m00 = nm00; 5026 dest.m01 = nm01; 5027 dest.m02 = nm02; 5028 dest.m10 = nm10; 5029 dest.m11 = nm11; 5030 dest.m12 = nm12; 5031 dest.m20 = nm20; 5032 dest.m21 = nm21; 5033 dest.m22 = nm22; 5034 dest.m30 = 0.0; 5035 dest.m31 = 0.0; 5036 dest.m32 = 0.0; 5037 dest.properties = properties & ~PROPERTY_TRANSLATION; 5038 return dest; 5039 } 5040 5041 /** 5042 * Normalize the left 3x3 submatrix of this matrix. 5043 * <p> 5044 * The resulting matrix will map unit vectors to unit vectors, though a pair of orthogonal input unit 5045 * vectors need not be mapped to a pair of orthogonal output vectors if the original matrix was not orthogonal itself 5046 * (i.e. had <i>skewing</i>). 5047 * 5048 * @return this 5049 */ 5050 ref public Matrix4x3d normalize3x3() return { 5051 normalize3x3(this); 5052 return this; 5053 } 5054 5055 public Matrix4x3d normalize3x3(ref Matrix4x3d dest) { 5056 double invXlen = Math.invsqrt(m00 * m00 + m01 * m01 + m02 * m02); 5057 double invYlen = Math.invsqrt(m10 * m10 + m11 * m11 + m12 * m12); 5058 double invZlen = Math.invsqrt(m20 * m20 + m21 * m21 + m22 * m22); 5059 dest.m00 = m00 * invXlen; dest.m01 = m01 * invXlen; dest.m02 = m02 * invXlen; 5060 dest.m10 = m10 * invYlen; dest.m11 = m11 * invYlen; dest.m12 = m12 * invYlen; 5061 dest.m20 = m20 * invZlen; dest.m21 = m21 * invZlen; dest.m22 = m22 * invZlen; 5062 return dest; 5063 } 5064 5065 public Matrix3d normalize3x3(Matrix3d dest) { 5066 double invXlen = Math.invsqrt(m00 * m00 + m01 * m01 + m02 * m02); 5067 double invYlen = Math.invsqrt(m10 * m10 + m11 * m11 + m12 * m12); 5068 double invZlen = Math.invsqrt(m20 * m20 + m21 * m21 + m22 * m22); 5069 dest.m00 = (m00 * invXlen); dest.m01 = (m01 * invXlen); dest.m02 = (m02 * invXlen); 5070 dest.m10 = (m10 * invYlen); dest.m11 = (m11 * invYlen); dest.m12 = (m12 * invYlen); 5071 dest.m20 = (m20 * invZlen); dest.m21 = (m21 * invZlen); dest.m22 = (m22 * invZlen); 5072 return dest; 5073 } 5074 5075 public Matrix4x3d reflect(double a, double b, double c, double d, ref Matrix4x3d dest) { 5076 if ((properties & PROPERTY_IDENTITY) != 0) 5077 return dest.reflection(a, b, c, d); 5078 5079 double da = a + a, db = b + b, dc = c + c, dd = d + d; 5080 double rm00 = 1.0 - da * a; 5081 double rm01 = -da * b; 5082 double rm02 = -da * c; 5083 double rm10 = -db * a; 5084 double rm11 = 1.0 - db * b; 5085 double rm12 = -db * c; 5086 double rm20 = -dc * a; 5087 double rm21 = -dc * b; 5088 double rm22 = 1.0 - dc * c; 5089 double rm30 = -dd * a; 5090 double rm31 = -dd * b; 5091 double rm32 = -dd * c; 5092 5093 // matrix multiplication 5094 dest.m30 = m00 * rm30 + m10 * rm31 + m20 * rm32 + m30; 5095 dest.m31 = m01 * rm30 + m11 * rm31 + m21 * rm32 + m31; 5096 dest.m32 = m02 * rm30 + m12 * rm31 + m22 * rm32 + m32; 5097 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 5098 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 5099 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 5100 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 5101 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 5102 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 5103 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 5104 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 5105 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 5106 dest.m00 = nm00; 5107 dest.m01 = nm01; 5108 dest.m02 = nm02; 5109 dest.m10 = nm10; 5110 dest.m11 = nm11; 5111 dest.m12 = nm12; 5112 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 5113 5114 return dest; 5115 } 5116 5117 /** 5118 * Apply a mirror/reflection transformation to this matrix that reflects about the given plane 5119 * specified via the equation <code>x*a + y*b + z*c + d = 0</code>. 5120 * <p> 5121 * The vector <code>(a, b, c)</code> must be a unit vector. 5122 * <p> 5123 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the reflection matrix, 5124 * then the new matrix will be <code>M * R</code>. So when transforming a 5125 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 5126 * reflection will be applied first! 5127 * <p> 5128 * Reference: <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/bb281733(v=vs.85).aspx">msdn.microsoft.com</a> 5129 * 5130 * @param a 5131 * the x factor in the plane equation 5132 * @param b 5133 * the y factor in the plane equation 5134 * @param c 5135 * the z factor in the plane equation 5136 * @param d 5137 * the constant in the plane equation 5138 * @return this 5139 */ 5140 ref public Matrix4x3d reflect(double a, double b, double c, double d) return { 5141 reflect(a, b, c, d, this); 5142 return this; 5143 } 5144 5145 /** 5146 * Apply a mirror/reflection transformation to this matrix that reflects about the given plane 5147 * specified via the plane normal and a point on the plane. 5148 * <p> 5149 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the reflection matrix, 5150 * then the new matrix will be <code>M * R</code>. So when transforming a 5151 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 5152 * reflection will be applied first! 5153 * 5154 * @param nx 5155 * the x-coordinate of the plane normal 5156 * @param ny 5157 * the y-coordinate of the plane normal 5158 * @param nz 5159 * the z-coordinate of the plane normal 5160 * @param px 5161 * the x-coordinate of a point on the plane 5162 * @param py 5163 * the y-coordinate of a point on the plane 5164 * @param pz 5165 * the z-coordinate of a point on the plane 5166 * @return this 5167 */ 5168 ref public Matrix4x3d reflect(double nx, double ny, double nz, double px, double py, double pz) return { 5169 reflect(nx, ny, nz, px, py, pz, this); 5170 return this; 5171 } 5172 5173 public Matrix4x3d reflect(double nx, double ny, double nz, double px, double py, double pz, ref Matrix4x3d dest) { 5174 double invLength = Math.invsqrt(nx * nx + ny * ny + nz * nz); 5175 double nnx = nx * invLength; 5176 double nny = ny * invLength; 5177 double nnz = nz * invLength; 5178 /* See: http://mathworld.wolfram.com/Plane.html */ 5179 return reflect(nnx, nny, nnz, -nnx * px - nny * py - nnz * pz, dest); 5180 } 5181 5182 /** 5183 * Apply a mirror/reflection transformation to this matrix that reflects about the given plane 5184 * specified via the plane normal and a point on the plane. 5185 * <p> 5186 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the reflection matrix, 5187 * then the new matrix will be <code>M * R</code>. So when transforming a 5188 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 5189 * reflection will be applied first! 5190 * 5191 * @param normal 5192 * the plane normal 5193 * @param point 5194 * a point on the plane 5195 * @return this 5196 */ 5197 ref public Matrix4x3d reflect(Vector3d normal, Vector3d point) return { 5198 return reflect(normal.x, normal.y, normal.z, point.x, point.y, point.z); 5199 } 5200 5201 /** 5202 * Apply a mirror/reflection transformation to this matrix that reflects about a plane 5203 * specified via the plane orientation and a point on the plane. 5204 * <p> 5205 * This method can be used to build a reflection transformation based on the orientation of a mirror object in the scene. 5206 * It is assumed that the default mirror plane's normal is <code>(0, 0, 1)</code>. So, if the given {@link Quaterniond} is 5207 * the identity (does not apply any additional rotation), the reflection plane will be <code>z=0</code>, offset by the given <code>point</code>. 5208 * <p> 5209 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the reflection matrix, 5210 * then the new matrix will be <code>M * R</code>. So when transforming a 5211 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 5212 * reflection will be applied first! 5213 * 5214 * @param orientation 5215 * the plane orientation relative to an implied normal vector of <code>(0, 0, 1)</code> 5216 * @param point 5217 * a point on the plane 5218 * @return this 5219 */ 5220 ref public Matrix4x3d reflect(Quaterniond orientation, Vector3d point) return { 5221 reflect(orientation, point, this); 5222 return this; 5223 } 5224 5225 public Matrix4x3d reflect(Quaterniond orientation, Vector3d point, ref Matrix4x3d dest) { 5226 double num1 = orientation.x + orientation.x; 5227 double num2 = orientation.y + orientation.y; 5228 double num3 = orientation.z + orientation.z; 5229 double normalX = orientation.x * num3 + orientation.w * num2; 5230 double normalY = orientation.y * num3 - orientation.w * num1; 5231 double normalZ = 1.0 - (orientation.x * num1 + orientation.y * num2); 5232 return reflect(normalX, normalY, normalZ, point.x, point.y, point.z, dest); 5233 } 5234 5235 public Matrix4x3d reflect(Vector3d normal, Vector3d point, ref Matrix4x3d dest) { 5236 return reflect(normal.x, normal.y, normal.z, point.x, point.y, point.z, dest); 5237 } 5238 5239 /** 5240 * Set this matrix to a mirror/reflection transformation that reflects about the given plane 5241 * specified via the equation <code>x*a + y*b + z*c + d = 0</code>. 5242 * <p> 5243 * The vector <code>(a, b, c)</code> must be a unit vector. 5244 * <p> 5245 * Reference: <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/bb281733(v=vs.85).aspx">msdn.microsoft.com</a> 5246 * 5247 * @param a 5248 * the x factor in the plane equation 5249 * @param b 5250 * the y factor in the plane equation 5251 * @param c 5252 * the z factor in the plane equation 5253 * @param d 5254 * the constant in the plane equation 5255 * @return this 5256 */ 5257 ref public Matrix4x3d reflection(double a, double b, double c, double d) return { 5258 double da = a + a, db = b + b, dc = c + c, dd = d + d; 5259 m00 = 1.0 - da * a; 5260 m01 = -da * b; 5261 m02 = -da * c; 5262 m10 = -db * a; 5263 m11 = 1.0 - db * b; 5264 m12 = -db * c; 5265 m20 = -dc * a; 5266 m21 = -dc * b; 5267 m22 = 1.0 - dc * c; 5268 m30 = -dd * a; 5269 m31 = -dd * b; 5270 m32 = -dd * c; 5271 properties = PROPERTY_ORTHONORMAL; 5272 return this; 5273 } 5274 5275 /** 5276 * Set this matrix to a mirror/reflection transformation that reflects about the given plane 5277 * specified via the plane normal and a point on the plane. 5278 * 5279 * @param nx 5280 * the x-coordinate of the plane normal 5281 * @param ny 5282 * the y-coordinate of the plane normal 5283 * @param nz 5284 * the z-coordinate of the plane normal 5285 * @param px 5286 * the x-coordinate of a point on the plane 5287 * @param py 5288 * the y-coordinate of a point on the plane 5289 * @param pz 5290 * the z-coordinate of a point on the plane 5291 * @return this 5292 */ 5293 ref public Matrix4x3d reflection(double nx, double ny, double nz, double px, double py, double pz) return { 5294 double invLength = Math.invsqrt(nx * nx + ny * ny + nz * nz); 5295 double nnx = nx * invLength; 5296 double nny = ny * invLength; 5297 double nnz = nz * invLength; 5298 /* See: http://mathworld.wolfram.com/Plane.html */ 5299 return reflection(nnx, nny, nnz, -nnx * px - nny * py - nnz * pz); 5300 } 5301 5302 /** 5303 * Set this matrix to a mirror/reflection transformation that reflects about the given plane 5304 * specified via the plane normal and a point on the plane. 5305 * 5306 * @param normal 5307 * the plane normal 5308 * @param point 5309 * a point on the plane 5310 * @return this 5311 */ 5312 ref public Matrix4x3d reflection(Vector3d normal, Vector3d point) return { 5313 return reflection(normal.x, normal.y, normal.z, point.x, point.y, point.z); 5314 } 5315 5316 /** 5317 * Set this matrix to a mirror/reflection transformation that reflects about a plane 5318 * specified via the plane orientation and a point on the plane. 5319 * <p> 5320 * This method can be used to build a reflection transformation based on the orientation of a mirror object in the scene. 5321 * It is assumed that the default mirror plane's normal is <code>(0, 0, 1)</code>. So, if the given {@link Quaterniond} is 5322 * the identity (does not apply any additional rotation), the reflection plane will be <code>z=0</code>, offset by the given <code>point</code>. 5323 * 5324 * @param orientation 5325 * the plane orientation 5326 * @param point 5327 * a point on the plane 5328 * @return this 5329 */ 5330 ref public Matrix4x3d reflection(Quaterniond orientation, Vector3d point) return { 5331 double num1 = orientation.x + orientation.x; 5332 double num2 = orientation.y + orientation.y; 5333 double num3 = orientation.z + orientation.z; 5334 double normalX = orientation.x * num3 + orientation.w * num2; 5335 double normalY = orientation.y * num3 - orientation.w * num1; 5336 double normalZ = 1.0 - (orientation.x * num1 + orientation.y * num2); 5337 return reflection(normalX, normalY, normalZ, point.x, point.y, point.z); 5338 } 5339 5340 /** 5341 * Apply an orthographic projection transformation for a right-handed coordinate system 5342 * using the given NDC z range to this matrix and store the result in <code>dest</code>. 5343 * <p> 5344 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5345 * then the new matrix will be <code>M * O</code>. So when transforming a 5346 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5347 * orthographic projection transformation will be applied first! 5348 * <p> 5349 * In order to set the matrix to an orthographic projection without post-multiplying it, 5350 * use {@link #setOrtho(double, double, double, double, double, double, bool) setOrtho()}. 5351 * <p> 5352 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5353 * 5354 * @see #setOrtho(double, double, double, double, double, double, bool) 5355 * 5356 * @param left 5357 * the distance from the center to the left frustum edge 5358 * @param right 5359 * the distance from the center to the right frustum edge 5360 * @param bottom 5361 * the distance from the center to the bottom frustum edge 5362 * @param top 5363 * the distance from the center to the top frustum edge 5364 * @param zNear 5365 * near clipping plane distance 5366 * @param zFar 5367 * far clipping plane distance 5368 * @param zZeroToOne 5369 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5370 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5371 * @param dest 5372 * will hold the result 5373 * @return dest 5374 */ 5375 public Matrix4x3d ortho(double left, double right, double bottom, double top, double zNear, double zFar, bool zZeroToOne, ref Matrix4x3d dest) { 5376 // calculate right matrix elements 5377 double rm00 = 2.0 / (right - left); 5378 double rm11 = 2.0 / (top - bottom); 5379 double rm22 = (zZeroToOne ? 1.0 : 2.0) / (zNear - zFar); 5380 double rm30 = (left + right) / (left - right); 5381 double rm31 = (top + bottom) / (bottom - top); 5382 double rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 5383 5384 // perform optimized multiplication 5385 // compute the last column first, because other columns do not depend on it 5386 dest.m30 = m00 * rm30 + m10 * rm31 + m20 * rm32 + m30; 5387 dest.m31 = m01 * rm30 + m11 * rm31 + m21 * rm32 + m31; 5388 dest.m32 = m02 * rm30 + m12 * rm31 + m22 * rm32 + m32; 5389 dest.m00 = m00 * rm00; 5390 dest.m01 = m01 * rm00; 5391 dest.m02 = m02 * rm00; 5392 dest.m10 = m10 * rm11; 5393 dest.m11 = m11 * rm11; 5394 dest.m12 = m12 * rm11; 5395 dest.m20 = m20 * rm22; 5396 dest.m21 = m21 * rm22; 5397 dest.m22 = m22 * rm22; 5398 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 5399 5400 return dest; 5401 } 5402 5403 /** 5404 * Apply an orthographic projection transformation for a right-handed coordinate system 5405 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix and store the result in <code>dest</code>. 5406 * <p> 5407 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5408 * then the new matrix will be <code>M * O</code>. So when transforming a 5409 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5410 * orthographic projection transformation will be applied first! 5411 * <p> 5412 * In order to set the matrix to an orthographic projection without post-multiplying it, 5413 * use {@link #setOrtho(double, double, double, double, double, double) setOrtho()}. 5414 * <p> 5415 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5416 * 5417 * @see #setOrtho(double, double, double, double, double, double) 5418 * 5419 * @param left 5420 * the distance from the center to the left frustum edge 5421 * @param right 5422 * the distance from the center to the right frustum edge 5423 * @param bottom 5424 * the distance from the center to the bottom frustum edge 5425 * @param top 5426 * the distance from the center to the top frustum edge 5427 * @param zNear 5428 * near clipping plane distance 5429 * @param zFar 5430 * far clipping plane distance 5431 * @param dest 5432 * will hold the result 5433 * @return dest 5434 */ 5435 public Matrix4x3d ortho(double left, double right, double bottom, double top, double zNear, double zFar, ref Matrix4x3d dest) { 5436 return ortho(left, right, bottom, top, zNear, zFar, false, dest); 5437 } 5438 5439 /** 5440 * Apply an orthographic projection transformation for a right-handed coordinate system 5441 * using the given NDC z range to this matrix. 5442 * <p> 5443 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5444 * then the new matrix will be <code>M * O</code>. So when transforming a 5445 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5446 * orthographic projection transformation will be applied first! 5447 * <p> 5448 * In order to set the matrix to an orthographic projection without post-multiplying it, 5449 * use {@link #setOrtho(double, double, double, double, double, double, bool) setOrtho()}. 5450 * <p> 5451 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5452 * 5453 * @see #setOrtho(double, double, double, double, double, double, bool) 5454 * 5455 * @param left 5456 * the distance from the center to the left frustum edge 5457 * @param right 5458 * the distance from the center to the right frustum edge 5459 * @param bottom 5460 * the distance from the center to the bottom frustum edge 5461 * @param top 5462 * the distance from the center to the top frustum edge 5463 * @param zNear 5464 * near clipping plane distance 5465 * @param zFar 5466 * far clipping plane distance 5467 * @param zZeroToOne 5468 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5469 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5470 * @return this 5471 */ 5472 ref public Matrix4x3d ortho(double left, double right, double bottom, double top, double zNear, double zFar, bool zZeroToOne) return { 5473 ortho(left, right, bottom, top, zNear, zFar, zZeroToOne, this); 5474 return this; 5475 } 5476 5477 /** 5478 * Apply an orthographic projection transformation for a right-handed coordinate system 5479 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix. 5480 * <p> 5481 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5482 * then the new matrix will be <code>M * O</code>. So when transforming a 5483 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5484 * orthographic projection transformation will be applied first! 5485 * <p> 5486 * In order to set the matrix to an orthographic projection without post-multiplying it, 5487 * use {@link #setOrtho(double, double, double, double, double, double) setOrtho()}. 5488 * <p> 5489 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5490 * 5491 * @see #setOrtho(double, double, double, double, double, double) 5492 * 5493 * @param left 5494 * the distance from the center to the left frustum edge 5495 * @param right 5496 * the distance from the center to the right frustum edge 5497 * @param bottom 5498 * the distance from the center to the bottom frustum edge 5499 * @param top 5500 * the distance from the center to the top frustum edge 5501 * @param zNear 5502 * near clipping plane distance 5503 * @param zFar 5504 * far clipping plane distance 5505 * @return this 5506 */ 5507 ref public Matrix4x3d ortho(double left, double right, double bottom, double top, double zNear, double zFar) return { 5508 return ortho(left, right, bottom, top, zNear, zFar, false); 5509 } 5510 5511 /** 5512 * Apply an orthographic projection transformation for a left-handed coordiante system 5513 * using the given NDC z range to this matrix and store the result in <code>dest</code>. 5514 * <p> 5515 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5516 * then the new matrix will be <code>M * O</code>. So when transforming a 5517 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5518 * orthographic projection transformation will be applied first! 5519 * <p> 5520 * In order to set the matrix to an orthographic projection without post-multiplying it, 5521 * use {@link #setOrthoLH(double, double, double, double, double, double, bool) setOrthoLH()}. 5522 * <p> 5523 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5524 * 5525 * @see #setOrthoLH(double, double, double, double, double, double, bool) 5526 * 5527 * @param left 5528 * the distance from the center to the left frustum edge 5529 * @param right 5530 * the distance from the center to the right frustum edge 5531 * @param bottom 5532 * the distance from the center to the bottom frustum edge 5533 * @param top 5534 * the distance from the center to the top frustum edge 5535 * @param zNear 5536 * near clipping plane distance 5537 * @param zFar 5538 * far clipping plane distance 5539 * @param zZeroToOne 5540 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5541 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5542 * @param dest 5543 * will hold the result 5544 * @return dest 5545 */ 5546 public Matrix4x3d orthoLH(double left, double right, double bottom, double top, double zNear, double zFar, bool zZeroToOne, ref Matrix4x3d dest) { 5547 // calculate right matrix elements 5548 double rm00 = 2.0 / (right - left); 5549 double rm11 = 2.0 / (top - bottom); 5550 double rm22 = (zZeroToOne ? 1.0 : 2.0) / (zFar - zNear); 5551 double rm30 = (left + right) / (left - right); 5552 double rm31 = (top + bottom) / (bottom - top); 5553 double rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 5554 5555 // perform optimized multiplication 5556 // compute the last column first, because other columns do not depend on it 5557 dest.m30 = m00 * rm30 + m10 * rm31 + m20 * rm32 + m30; 5558 dest.m31 = m01 * rm30 + m11 * rm31 + m21 * rm32 + m31; 5559 dest.m32 = m02 * rm30 + m12 * rm31 + m22 * rm32 + m32; 5560 dest.m00 = m00 * rm00; 5561 dest.m01 = m01 * rm00; 5562 dest.m02 = m02 * rm00; 5563 dest.m10 = m10 * rm11; 5564 dest.m11 = m11 * rm11; 5565 dest.m12 = m12 * rm11; 5566 dest.m20 = m20 * rm22; 5567 dest.m21 = m21 * rm22; 5568 dest.m22 = m22 * rm22; 5569 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 5570 5571 return dest; 5572 } 5573 5574 /** 5575 * Apply an orthographic projection transformation for a left-handed coordiante system 5576 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix and store the result in <code>dest</code>. 5577 * <p> 5578 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5579 * then the new matrix will be <code>M * O</code>. So when transforming a 5580 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5581 * orthographic projection transformation will be applied first! 5582 * <p> 5583 * In order to set the matrix to an orthographic projection without post-multiplying it, 5584 * use {@link #setOrthoLH(double, double, double, double, double, double) setOrthoLH()}. 5585 * <p> 5586 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5587 * 5588 * @see #setOrthoLH(double, double, double, double, double, double) 5589 * 5590 * @param left 5591 * the distance from the center to the left frustum edge 5592 * @param right 5593 * the distance from the center to the right frustum edge 5594 * @param bottom 5595 * the distance from the center to the bottom frustum edge 5596 * @param top 5597 * the distance from the center to the top frustum edge 5598 * @param zNear 5599 * near clipping plane distance 5600 * @param zFar 5601 * far clipping plane distance 5602 * @param dest 5603 * will hold the result 5604 * @return dest 5605 */ 5606 public Matrix4x3d orthoLH(double left, double right, double bottom, double top, double zNear, double zFar, ref Matrix4x3d dest) { 5607 return orthoLH(left, right, bottom, top, zNear, zFar, false, dest); 5608 } 5609 5610 /** 5611 * Apply an orthographic projection transformation for a left-handed coordiante system 5612 * using the given NDC z range to this matrix. 5613 * <p> 5614 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5615 * then the new matrix will be <code>M * O</code>. So when transforming a 5616 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5617 * orthographic projection transformation will be applied first! 5618 * <p> 5619 * In order to set the matrix to an orthographic projection without post-multiplying it, 5620 * use {@link #setOrthoLH(double, double, double, double, double, double, bool) setOrthoLH()}. 5621 * <p> 5622 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5623 * 5624 * @see #setOrthoLH(double, double, double, double, double, double, bool) 5625 * 5626 * @param left 5627 * the distance from the center to the left frustum edge 5628 * @param right 5629 * the distance from the center to the right frustum edge 5630 * @param bottom 5631 * the distance from the center to the bottom frustum edge 5632 * @param top 5633 * the distance from the center to the top frustum edge 5634 * @param zNear 5635 * near clipping plane distance 5636 * @param zFar 5637 * far clipping plane distance 5638 * @param zZeroToOne 5639 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5640 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5641 * @return this 5642 */ 5643 ref public Matrix4x3d orthoLH(double left, double right, double bottom, double top, double zNear, double zFar, bool zZeroToOne) return { 5644 orthoLH(left, right, bottom, top, zNear, zFar, zZeroToOne, this); 5645 return this; 5646 } 5647 5648 /** 5649 * Apply an orthographic projection transformation for a left-handed coordiante system 5650 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix. 5651 * <p> 5652 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5653 * then the new matrix will be <code>M * O</code>. So when transforming a 5654 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5655 * orthographic projection transformation will be applied first! 5656 * <p> 5657 * In order to set the matrix to an orthographic projection without post-multiplying it, 5658 * use {@link #setOrthoLH(double, double, double, double, double, double) setOrthoLH()}. 5659 * <p> 5660 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5661 * 5662 * @see #setOrthoLH(double, double, double, double, double, double) 5663 * 5664 * @param left 5665 * the distance from the center to the left frustum edge 5666 * @param right 5667 * the distance from the center to the right frustum edge 5668 * @param bottom 5669 * the distance from the center to the bottom frustum edge 5670 * @param top 5671 * the distance from the center to the top frustum edge 5672 * @param zNear 5673 * near clipping plane distance 5674 * @param zFar 5675 * far clipping plane distance 5676 * @return this 5677 */ 5678 ref public Matrix4x3d orthoLH(double left, double right, double bottom, double top, double zNear, double zFar) return { 5679 return orthoLH(left, right, bottom, top, zNear, zFar, false); 5680 } 5681 5682 /** 5683 * Set this matrix to be an orthographic projection transformation for a right-handed coordinate system 5684 * using the given NDC z range. 5685 * <p> 5686 * In order to apply the orthographic projection to an already existing transformation, 5687 * use {@link #ortho(double, double, double, double, double, double, bool) ortho()}. 5688 * <p> 5689 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5690 * 5691 * @see #ortho(double, double, double, double, double, double, bool) 5692 * 5693 * @param left 5694 * the distance from the center to the left frustum edge 5695 * @param right 5696 * the distance from the center to the right frustum edge 5697 * @param bottom 5698 * the distance from the center to the bottom frustum edge 5699 * @param top 5700 * the distance from the center to the top frustum edge 5701 * @param zNear 5702 * near clipping plane distance 5703 * @param zFar 5704 * far clipping plane distance 5705 * @param zZeroToOne 5706 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5707 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5708 * @return this 5709 */ 5710 ref public Matrix4x3d setOrtho(double left, double right, double bottom, double top, double zNear, double zFar, bool zZeroToOne) return { 5711 m00 = 2.0 / (right - left); 5712 m01 = 0.0; 5713 m02 = 0.0; 5714 m10 = 0.0; 5715 m11 = 2.0 / (top - bottom); 5716 m12 = 0.0; 5717 m20 = 0.0; 5718 m21 = 0.0; 5719 m22 = (zZeroToOne ? 1.0 : 2.0) / (zNear - zFar); 5720 m30 = (right + left) / (left - right); 5721 m31 = (top + bottom) / (bottom - top); 5722 m32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 5723 properties = 0; 5724 return this; 5725 } 5726 5727 /** 5728 * Set this matrix to be an orthographic projection transformation for a right-handed coordinate system 5729 * using OpenGL's NDC z range of <code>[-1..+1]</code>. 5730 * <p> 5731 * In order to apply the orthographic projection to an already existing transformation, 5732 * use {@link #ortho(double, double, double, double, double, double) ortho()}. 5733 * <p> 5734 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5735 * 5736 * @see #ortho(double, double, double, double, double, double) 5737 * 5738 * @param left 5739 * the distance from the center to the left frustum edge 5740 * @param right 5741 * the distance from the center to the right frustum edge 5742 * @param bottom 5743 * the distance from the center to the bottom frustum edge 5744 * @param top 5745 * the distance from the center to the top frustum edge 5746 * @param zNear 5747 * near clipping plane distance 5748 * @param zFar 5749 * far clipping plane distance 5750 * @return this 5751 */ 5752 ref public Matrix4x3d setOrtho(double left, double right, double bottom, double top, double zNear, double zFar) return { 5753 return setOrtho(left, right, bottom, top, zNear, zFar, false); 5754 } 5755 5756 /** 5757 * Set this matrix to be an orthographic projection transformation for a left-handed coordinate system 5758 * using the given NDC z range. 5759 * <p> 5760 * In order to apply the orthographic projection to an already existing transformation, 5761 * use {@link #orthoLH(double, double, double, double, double, double, bool) orthoLH()}. 5762 * <p> 5763 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5764 * 5765 * @see #orthoLH(double, double, double, double, double, double, bool) 5766 * 5767 * @param left 5768 * the distance from the center to the left frustum edge 5769 * @param right 5770 * the distance from the center to the right frustum edge 5771 * @param bottom 5772 * the distance from the center to the bottom frustum edge 5773 * @param top 5774 * the distance from the center to the top frustum edge 5775 * @param zNear 5776 * near clipping plane distance 5777 * @param zFar 5778 * far clipping plane distance 5779 * @param zZeroToOne 5780 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5781 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5782 * @return this 5783 */ 5784 ref public Matrix4x3d setOrthoLH(double left, double right, double bottom, double top, double zNear, double zFar, bool zZeroToOne) return { 5785 m00 = 2.0 / (right - left); 5786 m01 = 0.0; 5787 m02 = 0.0; 5788 m10 = 0.0; 5789 m11 = 2.0 / (top - bottom); 5790 m12 = 0.0; 5791 m20 = 0.0; 5792 m21 = 0.0; 5793 m22 = (zZeroToOne ? 1.0 : 2.0) / (zFar - zNear); 5794 m30 = (right + left) / (left - right); 5795 m31 = (top + bottom) / (bottom - top); 5796 m32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 5797 properties = 0; 5798 return this; 5799 } 5800 5801 /** 5802 * Set this matrix to be an orthographic projection transformation for a left-handed coordinate system 5803 * using OpenGL's NDC z range of <code>[-1..+1]</code>. 5804 * <p> 5805 * In order to apply the orthographic projection to an already existing transformation, 5806 * use {@link #orthoLH(double, double, double, double, double, double) orthoLH()}. 5807 * <p> 5808 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5809 * 5810 * @see #orthoLH(double, double, double, double, double, double) 5811 * 5812 * @param left 5813 * the distance from the center to the left frustum edge 5814 * @param right 5815 * the distance from the center to the right frustum edge 5816 * @param bottom 5817 * the distance from the center to the bottom frustum edge 5818 * @param top 5819 * the distance from the center to the top frustum edge 5820 * @param zNear 5821 * near clipping plane distance 5822 * @param zFar 5823 * far clipping plane distance 5824 * @return this 5825 */ 5826 ref public Matrix4x3d setOrthoLH(double left, double right, double bottom, double top, double zNear, double zFar) return { 5827 return setOrthoLH(left, right, bottom, top, zNear, zFar, false); 5828 } 5829 5830 /** 5831 * Apply a symmetric orthographic projection transformation for a right-handed coordinate system 5832 * using the given NDC z range to this matrix and store the result in <code>dest</code>. 5833 * <p> 5834 * This method is equivalent to calling {@link #ortho(double, double, double, double, double, double, bool, Matrix4x3d) ortho()} with 5835 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 5836 * <p> 5837 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5838 * then the new matrix will be <code>M * O</code>. So when transforming a 5839 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5840 * orthographic projection transformation will be applied first! 5841 * <p> 5842 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 5843 * use {@link #setOrthoSymmetric(double, double, double, double, bool) setOrthoSymmetric()}. 5844 * <p> 5845 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5846 * 5847 * @see #setOrthoSymmetric(double, double, double, double, bool) 5848 * 5849 * @param width 5850 * the distance between the right and left frustum edges 5851 * @param height 5852 * the distance between the top and bottom frustum edges 5853 * @param zNear 5854 * near clipping plane distance 5855 * @param zFar 5856 * far clipping plane distance 5857 * @param dest 5858 * will hold the result 5859 * @param zZeroToOne 5860 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5861 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5862 * @return dest 5863 */ 5864 public Matrix4x3d orthoSymmetric(double width, double height, double zNear, double zFar, bool zZeroToOne, ref Matrix4x3d dest) { 5865 // calculate right matrix elements 5866 double rm00 = 2.0 / width; 5867 double rm11 = 2.0 / height; 5868 double rm22 = (zZeroToOne ? 1.0 : 2.0) / (zNear - zFar); 5869 double rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 5870 5871 // perform optimized multiplication 5872 // compute the last column first, because other columns do not depend on it 5873 dest.m30 = m20 * rm32 + m30; 5874 dest.m31 = m21 * rm32 + m31; 5875 dest.m32 = m22 * rm32 + m32; 5876 dest.m00 = m00 * rm00; 5877 dest.m01 = m01 * rm00; 5878 dest.m02 = m02 * rm00; 5879 dest.m10 = m10 * rm11; 5880 dest.m11 = m11 * rm11; 5881 dest.m12 = m12 * rm11; 5882 dest.m20 = m20 * rm22; 5883 dest.m21 = m21 * rm22; 5884 dest.m22 = m22 * rm22; 5885 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 5886 5887 return dest; 5888 } 5889 5890 /** 5891 * Apply a symmetric orthographic projection transformation for a right-handed coordinate system 5892 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix and store the result in <code>dest</code>. 5893 * <p> 5894 * This method is equivalent to calling {@link #ortho(double, double, double, double, double, double, Matrix4x3d) ortho()} with 5895 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 5896 * <p> 5897 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5898 * then the new matrix will be <code>M * O</code>. So when transforming a 5899 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5900 * orthographic projection transformation will be applied first! 5901 * <p> 5902 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 5903 * use {@link #setOrthoSymmetric(double, double, double, double) setOrthoSymmetric()}. 5904 * <p> 5905 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5906 * 5907 * @see #setOrthoSymmetric(double, double, double, double) 5908 * 5909 * @param width 5910 * the distance between the right and left frustum edges 5911 * @param height 5912 * the distance between the top and bottom frustum edges 5913 * @param zNear 5914 * near clipping plane distance 5915 * @param zFar 5916 * far clipping plane distance 5917 * @param dest 5918 * will hold the result 5919 * @return dest 5920 */ 5921 public Matrix4x3d orthoSymmetric(double width, double height, double zNear, double zFar, ref Matrix4x3d dest) { 5922 return orthoSymmetric(width, height, zNear, zFar, false, dest); 5923 } 5924 5925 /** 5926 * Apply a symmetric orthographic projection transformation for a right-handed coordinate system 5927 * using the given NDC z range to this matrix. 5928 * <p> 5929 * This method is equivalent to calling {@link #ortho(double, double, double, double, double, double, bool) ortho()} with 5930 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 5931 * <p> 5932 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5933 * then the new matrix will be <code>M * O</code>. So when transforming a 5934 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5935 * orthographic projection transformation will be applied first! 5936 * <p> 5937 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 5938 * use {@link #setOrthoSymmetric(double, double, double, double, bool) setOrthoSymmetric()}. 5939 * <p> 5940 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5941 * 5942 * @see #setOrthoSymmetric(double, double, double, double, bool) 5943 * 5944 * @param width 5945 * the distance between the right and left frustum edges 5946 * @param height 5947 * the distance between the top and bottom frustum edges 5948 * @param zNear 5949 * near clipping plane distance 5950 * @param zFar 5951 * far clipping plane distance 5952 * @param zZeroToOne 5953 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5954 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5955 * @return this 5956 */ 5957 ref public Matrix4x3d orthoSymmetric(double width, double height, double zNear, double zFar, bool zZeroToOne) return { 5958 orthoSymmetric(width, height, zNear, zFar, zZeroToOne, this); 5959 return this; 5960 } 5961 5962 /** 5963 * Apply a symmetric orthographic projection transformation for a right-handed coordinate system 5964 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix. 5965 * <p> 5966 * This method is equivalent to calling {@link #ortho(double, double, double, double, double, double) ortho()} with 5967 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 5968 * <p> 5969 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5970 * then the new matrix will be <code>M * O</code>. So when transforming a 5971 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5972 * orthographic projection transformation will be applied first! 5973 * <p> 5974 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 5975 * use {@link #setOrthoSymmetric(double, double, double, double) setOrthoSymmetric()}. 5976 * <p> 5977 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5978 * 5979 * @see #setOrthoSymmetric(double, double, double, double) 5980 * 5981 * @param width 5982 * the distance between the right and left frustum edges 5983 * @param height 5984 * the distance between the top and bottom frustum edges 5985 * @param zNear 5986 * near clipping plane distance 5987 * @param zFar 5988 * far clipping plane distance 5989 * @return this 5990 */ 5991 ref public Matrix4x3d orthoSymmetric(double width, double height, double zNear, double zFar) return { 5992 orthoSymmetric(width, height, zNear, zFar, false, this); 5993 return this; 5994 } 5995 5996 /** 5997 * Apply a symmetric orthographic projection transformation for a left-handed coordinate system 5998 * using the given NDC z range to this matrix and store the result in <code>dest</code>. 5999 * <p> 6000 * This method is equivalent to calling {@link #orthoLH(double, double, double, double, double, double, bool, Matrix4x3d) orthoLH()} with 6001 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6002 * <p> 6003 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6004 * then the new matrix will be <code>M * O</code>. So when transforming a 6005 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6006 * orthographic projection transformation will be applied first! 6007 * <p> 6008 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 6009 * use {@link #setOrthoSymmetricLH(double, double, double, double, bool) setOrthoSymmetricLH()}. 6010 * <p> 6011 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6012 * 6013 * @see #setOrthoSymmetricLH(double, double, double, double, bool) 6014 * 6015 * @param width 6016 * the distance between the right and left frustum edges 6017 * @param height 6018 * the distance between the top and bottom frustum edges 6019 * @param zNear 6020 * near clipping plane distance 6021 * @param zFar 6022 * far clipping plane distance 6023 * @param dest 6024 * will hold the result 6025 * @param zZeroToOne 6026 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 6027 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 6028 * @return dest 6029 */ 6030 public Matrix4x3d orthoSymmetricLH(double width, double height, double zNear, double zFar, bool zZeroToOne, ref Matrix4x3d dest) { 6031 // calculate right matrix elements 6032 double rm00 = 2.0 / width; 6033 double rm11 = 2.0 / height; 6034 double rm22 = (zZeroToOne ? 1.0 : 2.0) / (zFar - zNear); 6035 double rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 6036 6037 // perform optimized multiplication 6038 // compute the last column first, because other columns do not depend on it 6039 dest.m30 = m20 * rm32 + m30; 6040 dest.m31 = m21 * rm32 + m31; 6041 dest.m32 = m22 * rm32 + m32; 6042 dest.m00 = m00 * rm00; 6043 dest.m01 = m01 * rm00; 6044 dest.m02 = m02 * rm00; 6045 dest.m10 = m10 * rm11; 6046 dest.m11 = m11 * rm11; 6047 dest.m12 = m12 * rm11; 6048 dest.m20 = m20 * rm22; 6049 dest.m21 = m21 * rm22; 6050 dest.m22 = m22 * rm22; 6051 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 6052 6053 return dest; 6054 } 6055 6056 /** 6057 * Apply a symmetric orthographic projection transformation for a left-handed coordinate system 6058 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix and store the result in <code>dest</code>. 6059 * <p> 6060 * This method is equivalent to calling {@link #orthoLH(double, double, double, double, double, double, Matrix4x3d) orthoLH()} with 6061 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6062 * <p> 6063 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6064 * then the new matrix will be <code>M * O</code>. So when transforming a 6065 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6066 * orthographic projection transformation will be applied first! 6067 * <p> 6068 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 6069 * use {@link #setOrthoSymmetricLH(double, double, double, double) setOrthoSymmetricLH()}. 6070 * <p> 6071 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6072 * 6073 * @see #setOrthoSymmetricLH(double, double, double, double) 6074 * 6075 * @param width 6076 * the distance between the right and left frustum edges 6077 * @param height 6078 * the distance between the top and bottom frustum edges 6079 * @param zNear 6080 * near clipping plane distance 6081 * @param zFar 6082 * far clipping plane distance 6083 * @param dest 6084 * will hold the result 6085 * @return dest 6086 */ 6087 public Matrix4x3d orthoSymmetricLH(double width, double height, double zNear, double zFar, ref Matrix4x3d dest) { 6088 return orthoSymmetricLH(width, height, zNear, zFar, false, dest); 6089 } 6090 6091 /** 6092 * Apply a symmetric orthographic projection transformation for a left-handed coordinate system 6093 * using the given NDC z range to this matrix. 6094 * <p> 6095 * This method is equivalent to calling {@link #orthoLH(double, double, double, double, double, double, bool) orthoLH()} with 6096 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6097 * <p> 6098 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6099 * then the new matrix will be <code>M * O</code>. So when transforming a 6100 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6101 * orthographic projection transformation will be applied first! 6102 * <p> 6103 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 6104 * use {@link #setOrthoSymmetricLH(double, double, double, double, bool) setOrthoSymmetricLH()}. 6105 * <p> 6106 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6107 * 6108 * @see #setOrthoSymmetricLH(double, double, double, double, bool) 6109 * 6110 * @param width 6111 * the distance between the right and left frustum edges 6112 * @param height 6113 * the distance between the top and bottom frustum edges 6114 * @param zNear 6115 * near clipping plane distance 6116 * @param zFar 6117 * far clipping plane distance 6118 * @param zZeroToOne 6119 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 6120 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 6121 * @return this 6122 */ 6123 ref public Matrix4x3d orthoSymmetricLH(double width, double height, double zNear, double zFar, bool zZeroToOne) return { 6124 orthoSymmetricLH(width, height, zNear, zFar, zZeroToOne, this); 6125 return this; 6126 } 6127 6128 /** 6129 * Apply a symmetric orthographic projection transformation for a left-handed coordinate system 6130 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix. 6131 * <p> 6132 * This method is equivalent to calling {@link #orthoLH(double, double, double, double, double, double) orthoLH()} with 6133 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6134 * <p> 6135 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6136 * then the new matrix will be <code>M * O</code>. So when transforming a 6137 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6138 * orthographic projection transformation will be applied first! 6139 * <p> 6140 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 6141 * use {@link #setOrthoSymmetricLH(double, double, double, double) setOrthoSymmetricLH()}. 6142 * <p> 6143 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6144 * 6145 * @see #setOrthoSymmetricLH(double, double, double, double) 6146 * 6147 * @param width 6148 * the distance between the right and left frustum edges 6149 * @param height 6150 * the distance between the top and bottom frustum edges 6151 * @param zNear 6152 * near clipping plane distance 6153 * @param zFar 6154 * far clipping plane distance 6155 * @return this 6156 */ 6157 ref public Matrix4x3d orthoSymmetricLH(double width, double height, double zNear, double zFar) return { 6158 orthoSymmetricLH(width, height, zNear, zFar, false, this); 6159 return this; 6160 } 6161 6162 /** 6163 * Set this matrix to be a symmetric orthographic projection transformation for a right-handed coordinate system 6164 * using the given NDC z range. 6165 * <p> 6166 * This method is equivalent to calling {@link #setOrtho(double, double, double, double, double, double, bool) setOrtho()} with 6167 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6168 * <p> 6169 * In order to apply the symmetric orthographic projection to an already existing transformation, 6170 * use {@link #orthoSymmetric(double, double, double, double, bool) orthoSymmetric()}. 6171 * <p> 6172 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6173 * 6174 * @see #orthoSymmetric(double, double, double, double, bool) 6175 * 6176 * @param width 6177 * the distance between the right and left frustum edges 6178 * @param height 6179 * the distance between the top and bottom frustum edges 6180 * @param zNear 6181 * near clipping plane distance 6182 * @param zFar 6183 * far clipping plane distance 6184 * @param zZeroToOne 6185 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 6186 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 6187 * @return this 6188 */ 6189 ref public Matrix4x3d setOrthoSymmetric(double width, double height, double zNear, double zFar, bool zZeroToOne) return { 6190 m00 = 2.0 / width; 6191 m01 = 0.0; 6192 m02 = 0.0; 6193 m10 = 0.0; 6194 m11 = 2.0 / height; 6195 m12 = 0.0; 6196 m20 = 0.0; 6197 m21 = 0.0; 6198 m22 = (zZeroToOne ? 1.0 : 2.0) / (zNear - zFar); 6199 m30 = 0.0; 6200 m31 = 0.0; 6201 m32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 6202 properties = 0; 6203 return this; 6204 } 6205 6206 /** 6207 * Set this matrix to be a symmetric orthographic projection transformation for a right-handed coordinate system 6208 * using OpenGL's NDC z range of <code>[-1..+1]</code>. 6209 * <p> 6210 * This method is equivalent to calling {@link #setOrtho(double, double, double, double, double, double) setOrtho()} with 6211 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6212 * <p> 6213 * In order to apply the symmetric orthographic projection to an already existing transformation, 6214 * use {@link #orthoSymmetric(double, double, double, double) orthoSymmetric()}. 6215 * <p> 6216 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6217 * 6218 * @see #orthoSymmetric(double, double, double, double) 6219 * 6220 * @param width 6221 * the distance between the right and left frustum edges 6222 * @param height 6223 * the distance between the top and bottom frustum edges 6224 * @param zNear 6225 * near clipping plane distance 6226 * @param zFar 6227 * far clipping plane distance 6228 * @return this 6229 */ 6230 ref public Matrix4x3d setOrthoSymmetric(double width, double height, double zNear, double zFar) return { 6231 return setOrthoSymmetric(width, height, zNear, zFar, false); 6232 } 6233 6234 /** 6235 * Set this matrix to be a symmetric orthographic projection transformation for a left-handed coordinate system using the given NDC z range. 6236 * <p> 6237 * This method is equivalent to calling {@link #setOrtho(double, double, double, double, double, double, bool) setOrtho()} with 6238 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6239 * <p> 6240 * In order to apply the symmetric orthographic projection to an already existing transformation, 6241 * use {@link #orthoSymmetricLH(double, double, double, double, bool) orthoSymmetricLH()}. 6242 * <p> 6243 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6244 * 6245 * @see #orthoSymmetricLH(double, double, double, double, bool) 6246 * 6247 * @param width 6248 * the distance between the right and left frustum edges 6249 * @param height 6250 * the distance between the top and bottom frustum edges 6251 * @param zNear 6252 * near clipping plane distance 6253 * @param zFar 6254 * far clipping plane distance 6255 * @param zZeroToOne 6256 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 6257 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 6258 * @return this 6259 */ 6260 ref public Matrix4x3d setOrthoSymmetricLH(double width, double height, double zNear, double zFar, bool zZeroToOne) return { 6261 m00 = 2.0 / width; 6262 m01 = 0.0; 6263 m02 = 0.0; 6264 m10 = 0.0; 6265 m11 = 2.0 / height; 6266 m12 = 0.0; 6267 m20 = 0.0; 6268 m21 = 0.0; 6269 m22 = (zZeroToOne ? 1.0 : 2.0) / (zFar - zNear); 6270 m30 = 0.0; 6271 m31 = 0.0; 6272 m32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 6273 properties = 0; 6274 return this; 6275 } 6276 6277 /** 6278 * Set this matrix to be a symmetric orthographic projection transformation for a left-handed coordinate system 6279 * using OpenGL's NDC z range of <code>[-1..+1]</code>. 6280 * <p> 6281 * This method is equivalent to calling {@link #setOrthoLH(double, double, double, double, double, double) setOrthoLH()} with 6282 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6283 * <p> 6284 * In order to apply the symmetric orthographic projection to an already existing transformation, 6285 * use {@link #orthoSymmetricLH(double, double, double, double) orthoSymmetricLH()}. 6286 * <p> 6287 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6288 * 6289 * @see #orthoSymmetricLH(double, double, double, double) 6290 * 6291 * @param width 6292 * the distance between the right and left frustum edges 6293 * @param height 6294 * the distance between the top and bottom frustum edges 6295 * @param zNear 6296 * near clipping plane distance 6297 * @param zFar 6298 * far clipping plane distance 6299 * @return this 6300 */ 6301 ref public Matrix4x3d setOrthoSymmetricLH(double width, double height, double zNear, double zFar) return { 6302 return setOrthoSymmetricLH(width, height, zNear, zFar, false); 6303 } 6304 6305 /** 6306 * Apply an orthographic projection transformation for a right-handed coordinate system 6307 * to this matrix and store the result in <code>dest</code>. 6308 * <p> 6309 * This method is equivalent to calling {@link #ortho(double, double, double, double, double, double, Matrix4x3d) ortho()} with 6310 * <code>zNear=-1</code> and <code>zFar=+1</code>. 6311 * <p> 6312 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6313 * then the new matrix will be <code>M * O</code>. So when transforming a 6314 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6315 * orthographic projection transformation will be applied first! 6316 * <p> 6317 * In order to set the matrix to an orthographic projection without post-multiplying it, 6318 * use {@link #setOrtho2D(double, double, double, double) setOrtho()}. 6319 * <p> 6320 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6321 * 6322 * @see #ortho(double, double, double, double, double, double, Matrix4x3d) 6323 * @see #setOrtho2D(double, double, double, double) 6324 * 6325 * @param left 6326 * the distance from the center to the left frustum edge 6327 * @param right 6328 * the distance from the center to the right frustum edge 6329 * @param bottom 6330 * the distance from the center to the bottom frustum edge 6331 * @param top 6332 * the distance from the center to the top frustum edge 6333 * @param dest 6334 * will hold the result 6335 * @return dest 6336 */ 6337 public Matrix4x3d ortho2D(double left, double right, double bottom, double top, ref Matrix4x3d dest) { 6338 // calculate right matrix elements 6339 double rm00 = 2.0 / (right - left); 6340 double rm11 = 2.0 / (top - bottom); 6341 double rm30 = -(right + left) / (right - left); 6342 double rm31 = -(top + bottom) / (top - bottom); 6343 6344 // perform optimized multiplication 6345 // compute the last column first, because other columns do not depend on it 6346 dest.m30 = m00 * rm30 + m10 * rm31 + m30; 6347 dest.m31 = m01 * rm30 + m11 * rm31 + m31; 6348 dest.m32 = m02 * rm30 + m12 * rm31 + m32; 6349 dest.m00 = m00 * rm00; 6350 dest.m01 = m01 * rm00; 6351 dest.m02 = m02 * rm00; 6352 dest.m10 = m10 * rm11; 6353 dest.m11 = m11 * rm11; 6354 dest.m12 = m12 * rm11; 6355 dest.m20 = -m20; 6356 dest.m21 = -m21; 6357 dest.m22 = -m22; 6358 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 6359 6360 return dest; 6361 } 6362 6363 /** 6364 * Apply an orthographic projection transformation for a right-handed coordinate system to this matrix. 6365 * <p> 6366 * This method is equivalent to calling {@link #ortho(double, double, double, double, double, double) ortho()} with 6367 * <code>zNear=-1</code> and <code>zFar=+1</code>. 6368 * <p> 6369 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6370 * then the new matrix will be <code>M * O</code>. So when transforming a 6371 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6372 * orthographic projection transformation will be applied first! 6373 * <p> 6374 * In order to set the matrix to an orthographic projection without post-multiplying it, 6375 * use {@link #setOrtho2D(double, double, double, double) setOrtho2D()}. 6376 * <p> 6377 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6378 * 6379 * @see #ortho(double, double, double, double, double, double) 6380 * @see #setOrtho2D(double, double, double, double) 6381 * 6382 * @param left 6383 * the distance from the center to the left frustum edge 6384 * @param right 6385 * the distance from the center to the right frustum edge 6386 * @param bottom 6387 * the distance from the center to the bottom frustum edge 6388 * @param top 6389 * the distance from the center to the top frustum edge 6390 * @return this 6391 */ 6392 ref public Matrix4x3d ortho2D(double left, double right, double bottom, double top) return { 6393 ortho2D(left, right, bottom, top, this); 6394 return this; 6395 } 6396 6397 /** 6398 * Apply an orthographic projection transformation for a left-handed coordinate system to this matrix and store the result in <code>dest</code>. 6399 * <p> 6400 * This method is equivalent to calling {@link #orthoLH(double, double, double, double, double, double, Matrix4x3d) orthoLH()} with 6401 * <code>zNear=-1</code> and <code>zFar=+1</code>. 6402 * <p> 6403 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6404 * then the new matrix will be <code>M * O</code>. So when transforming a 6405 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6406 * orthographic projection transformation will be applied first! 6407 * <p> 6408 * In order to set the matrix to an orthographic projection without post-multiplying it, 6409 * use {@link #setOrtho2DLH(double, double, double, double) setOrthoLH()}. 6410 * <p> 6411 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6412 * 6413 * @see #orthoLH(double, double, double, double, double, double, Matrix4x3d) 6414 * @see #setOrtho2DLH(double, double, double, double) 6415 * 6416 * @param left 6417 * the distance from the center to the left frustum edge 6418 * @param right 6419 * the distance from the center to the right frustum edge 6420 * @param bottom 6421 * the distance from the center to the bottom frustum edge 6422 * @param top 6423 * the distance from the center to the top frustum edge 6424 * @param dest 6425 * will hold the result 6426 * @return dest 6427 */ 6428 public Matrix4x3d ortho2DLH(double left, double right, double bottom, double top, ref Matrix4x3d dest) { 6429 // calculate right matrix elements 6430 double rm00 = 2.0 / (right - left); 6431 double rm11 = 2.0 / (top - bottom); 6432 double rm30 = -(right + left) / (right - left); 6433 double rm31 = -(top + bottom) / (top - bottom); 6434 6435 // perform optimized multiplication 6436 // compute the last column first, because other columns do not depend on it 6437 dest.m30 = m00 * rm30 + m10 * rm31 + m30; 6438 dest.m31 = m01 * rm30 + m11 * rm31 + m31; 6439 dest.m32 = m02 * rm30 + m12 * rm31 + m32; 6440 dest.m00 = m00 * rm00; 6441 dest.m01 = m01 * rm00; 6442 dest.m02 = m02 * rm00; 6443 dest.m10 = m10 * rm11; 6444 dest.m11 = m11 * rm11; 6445 dest.m12 = m12 * rm11; 6446 dest.m20 = m20; 6447 dest.m21 = m21; 6448 dest.m22 = m22; 6449 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 6450 6451 return dest; 6452 } 6453 6454 /** 6455 * Apply an orthographic projection transformation for a left-handed coordinate system to this matrix. 6456 * <p> 6457 * This method is equivalent to calling {@link #orthoLH(double, double, double, double, double, double) orthoLH()} with 6458 * <code>zNear=-1</code> and <code>zFar=+1</code>. 6459 * <p> 6460 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6461 * then the new matrix will be <code>M * O</code>. So when transforming a 6462 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6463 * orthographic projection transformation will be applied first! 6464 * <p> 6465 * In order to set the matrix to an orthographic projection without post-multiplying it, 6466 * use {@link #setOrtho2DLH(double, double, double, double) setOrtho2DLH()}. 6467 * <p> 6468 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6469 * 6470 * @see #orthoLH(double, double, double, double, double, double) 6471 * @see #setOrtho2DLH(double, double, double, double) 6472 * 6473 * @param left 6474 * the distance from the center to the left frustum edge 6475 * @param right 6476 * the distance from the center to the right frustum edge 6477 * @param bottom 6478 * the distance from the center to the bottom frustum edge 6479 * @param top 6480 * the distance from the center to the top frustum edge 6481 * @return this 6482 */ 6483 ref public Matrix4x3d ortho2DLH(double left, double right, double bottom, double top) return { 6484 ortho2DLH(left, right, bottom, top, this); 6485 return this; 6486 } 6487 6488 /** 6489 * Set this matrix to be an orthographic projection transformation for a right-handed coordinate system. 6490 * <p> 6491 * This method is equivalent to calling {@link #setOrtho(double, double, double, double, double, double) setOrtho()} with 6492 * <code>zNear=-1</code> and <code>zFar=+1</code>. 6493 * <p> 6494 * In order to apply the orthographic projection to an already existing transformation, 6495 * use {@link #ortho2D(double, double, double, double) ortho2D()}. 6496 * <p> 6497 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6498 * 6499 * @see #setOrtho(double, double, double, double, double, double) 6500 * @see #ortho2D(double, double, double, double) 6501 * 6502 * @param left 6503 * the distance from the center to the left frustum edge 6504 * @param right 6505 * the distance from the center to the right frustum edge 6506 * @param bottom 6507 * the distance from the center to the bottom frustum edge 6508 * @param top 6509 * the distance from the center to the top frustum edge 6510 * @return this 6511 */ 6512 ref public Matrix4x3d setOrtho2D(double left, double right, double bottom, double top) return { 6513 m00 = 2.0 / (right - left); 6514 m01 = 0.0; 6515 m02 = 0.0; 6516 m10 = 0.0; 6517 m11 = 2.0 / (top - bottom); 6518 m12 = 0.0; 6519 m20 = 0.0; 6520 m21 = 0.0; 6521 m22 = -1.0; 6522 m30 = -(right + left) / (right - left); 6523 m31 = -(top + bottom) / (top - bottom); 6524 m32 = 0.0; 6525 properties = 0; 6526 return this; 6527 } 6528 6529 /** 6530 * Set this matrix to be an orthographic projection transformation for a left-handed coordinate system. 6531 * <p> 6532 * This method is equivalent to calling {@link #setOrtho(double, double, double, double, double, double) setOrthoLH()} with 6533 * <code>zNear=-1</code> and <code>zFar=+1</code>. 6534 * <p> 6535 * In order to apply the orthographic projection to an already existing transformation, 6536 * use {@link #ortho2DLH(double, double, double, double) ortho2DLH()}. 6537 * <p> 6538 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6539 * 6540 * @see #setOrthoLH(double, double, double, double, double, double) 6541 * @see #ortho2DLH(double, double, double, double) 6542 * 6543 * @param left 6544 * the distance from the center to the left frustum edge 6545 * @param right 6546 * the distance from the center to the right frustum edge 6547 * @param bottom 6548 * the distance from the center to the bottom frustum edge 6549 * @param top 6550 * the distance from the center to the top frustum edge 6551 * @return this 6552 */ 6553 ref public Matrix4x3d setOrtho2DLH(double left, double right, double bottom, double top) return { 6554 m00 = 2.0 / (right - left); 6555 m01 = 0.0; 6556 m02 = 0.0; 6557 m10 = 0.0; 6558 m11 = 2.0 / (top - bottom); 6559 m12 = 0.0; 6560 m20 = 0.0; 6561 m21 = 0.0; 6562 m22 = 1.0; 6563 m30 = -(right + left) / (right - left); 6564 m31 = -(top + bottom) / (top - bottom); 6565 m32 = 0.0; 6566 properties = 0; 6567 return this; 6568 } 6569 6570 /** 6571 * Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code>. 6572 * <p> 6573 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix, 6574 * then the new matrix will be <code>M * L</code>. So when transforming a 6575 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the 6576 * lookalong rotation transformation will be applied first! 6577 * <p> 6578 * This is equivalent to calling 6579 * {@link #lookAt(Vector3d, Vector3d, Vector3d) lookAt} 6580 * with <code>eye = (0, 0, 0)</code> and <code>center = dir</code>. 6581 * <p> 6582 * In order to set the matrix to a lookalong transformation without post-multiplying it, 6583 * use {@link #setLookAlong(Vector3d, Vector3d) setLookAlong()}. 6584 * 6585 * @see #lookAlong(double, double, double, double, double, double) 6586 * @see #lookAt(Vector3d, Vector3d, Vector3d) 6587 * @see #setLookAlong(Vector3d, Vector3d) 6588 * 6589 * @param dir 6590 * the direction in space to look along 6591 * @param up 6592 * the direction of 'up' 6593 * @return this 6594 */ 6595 ref public Matrix4x3d lookAlong(ref Vector3d dir, Vector3d up) return { 6596 lookAlong(dir.x, dir.y, dir.z, up.x, up.y, up.z, this); 6597 return this; 6598 } 6599 6600 /** 6601 * Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code> 6602 * and store the result in <code>dest</code>. 6603 * <p> 6604 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix, 6605 * then the new matrix will be <code>M * L</code>. So when transforming a 6606 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the 6607 * lookalong rotation transformation will be applied first! 6608 * <p> 6609 * This is equivalent to calling 6610 * {@link #lookAt(Vector3d, Vector3d, Vector3d) lookAt} 6611 * with <code>eye = (0, 0, 0)</code> and <code>center = dir</code>. 6612 * <p> 6613 * In order to set the matrix to a lookalong transformation without post-multiplying it, 6614 * use {@link #setLookAlong(Vector3d, Vector3d) setLookAlong()}. 6615 * 6616 * @see #lookAlong(double, double, double, double, double, double) 6617 * @see #lookAt(Vector3d, Vector3d, Vector3d) 6618 * @see #setLookAlong(Vector3d, Vector3d) 6619 * 6620 * @param dir 6621 * the direction in space to look along 6622 * @param up 6623 * the direction of 'up' 6624 * @param dest 6625 * will hold the result 6626 * @return dest 6627 */ 6628 public Matrix4x3d lookAlong(ref Vector3d dir, Vector3d up, ref Matrix4x3d dest) { 6629 return lookAlong(dir.x, dir.y, dir.z, up.x, up.y, up.z, dest); 6630 } 6631 6632 /** 6633 * Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code> 6634 * and store the result in <code>dest</code>. 6635 * <p> 6636 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix, 6637 * then the new matrix will be <code>M * L</code>. So when transforming a 6638 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the 6639 * lookalong rotation transformation will be applied first! 6640 * <p> 6641 * This is equivalent to calling 6642 * {@link #lookAt(double, double, double, double, double, double, double, double, double) lookAt()} 6643 * with <code>eye = (0, 0, 0)</code> and <code>center = dir</code>. 6644 * <p> 6645 * In order to set the matrix to a lookalong transformation without post-multiplying it, 6646 * use {@link #setLookAlong(double, double, double, double, double, double) setLookAlong()} 6647 * 6648 * @see #lookAt(double, double, double, double, double, double, double, double, double) 6649 * @see #setLookAlong(double, double, double, double, double, double) 6650 * 6651 * @param dirX 6652 * the x-coordinate of the direction to look along 6653 * @param dirY 6654 * the y-coordinate of the direction to look along 6655 * @param dirZ 6656 * the z-coordinate of the direction to look along 6657 * @param upX 6658 * the x-coordinate of the up vector 6659 * @param upY 6660 * the y-coordinate of the up vector 6661 * @param upZ 6662 * the z-coordinate of the up vector 6663 * @param dest 6664 * will hold the result 6665 * @return dest 6666 */ 6667 public Matrix4x3d lookAlong(double dirX, double dirY, double dirZ, 6668 double upX, double upY, double upZ, ref Matrix4x3d dest) { 6669 if ((properties & PROPERTY_IDENTITY) != 0) 6670 return setLookAlong(dirX, dirY, dirZ, upX, upY, upZ); 6671 6672 // Normalize direction 6673 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 6674 dirX *= -invDirLength; 6675 dirY *= -invDirLength; 6676 dirZ *= -invDirLength; 6677 // left = up x direction 6678 double leftX, leftY, leftZ; 6679 leftX = upY * dirZ - upZ * dirY; 6680 leftY = upZ * dirX - upX * dirZ; 6681 leftZ = upX * dirY - upY * dirX; 6682 // normalize left 6683 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 6684 leftX *= invLeftLength; 6685 leftY *= invLeftLength; 6686 leftZ *= invLeftLength; 6687 // up = direction x left 6688 double upnX = dirY * leftZ - dirZ * leftY; 6689 double upnY = dirZ * leftX - dirX * leftZ; 6690 double upnZ = dirX * leftY - dirY * leftX; 6691 6692 // calculate right matrix elements 6693 double rm00 = leftX; 6694 double rm01 = upnX; 6695 double rm02 = dirX; 6696 double rm10 = leftY; 6697 double rm11 = upnY; 6698 double rm12 = dirY; 6699 double rm20 = leftZ; 6700 double rm21 = upnZ; 6701 double rm22 = dirZ; 6702 6703 // perform optimized matrix multiplication 6704 // introduce temporaries for dependent results 6705 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 6706 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 6707 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 6708 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 6709 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 6710 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 6711 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 6712 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 6713 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 6714 // set the rest of the matrix elements 6715 dest.m00 = nm00; 6716 dest.m01 = nm01; 6717 dest.m02 = nm02; 6718 dest.m10 = nm10; 6719 dest.m11 = nm11; 6720 dest.m12 = nm12; 6721 dest.m30 = m30; 6722 dest.m31 = m31; 6723 dest.m32 = m32; 6724 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 6725 6726 return dest; 6727 } 6728 6729 /** 6730 * Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code>. 6731 * <p> 6732 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix, 6733 * then the new matrix will be <code>M * L</code>. So when transforming a 6734 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the 6735 * lookalong rotation transformation will be applied first! 6736 * <p> 6737 * This is equivalent to calling 6738 * {@link #lookAt(double, double, double, double, double, double, double, double, double) lookAt()} 6739 * with <code>eye = (0, 0, 0)</code> and <code>center = dir</code>. 6740 * <p> 6741 * In order to set the matrix to a lookalong transformation without post-multiplying it, 6742 * use {@link #setLookAlong(double, double, double, double, double, double) setLookAlong()} 6743 * 6744 * @see #lookAt(double, double, double, double, double, double, double, double, double) 6745 * @see #setLookAlong(double, double, double, double, double, double) 6746 * 6747 * @param dirX 6748 * the x-coordinate of the direction to look along 6749 * @param dirY 6750 * the y-coordinate of the direction to look along 6751 * @param dirZ 6752 * the z-coordinate of the direction to look along 6753 * @param upX 6754 * the x-coordinate of the up vector 6755 * @param upY 6756 * the y-coordinate of the up vector 6757 * @param upZ 6758 * the z-coordinate of the up vector 6759 * @return this 6760 */ 6761 ref public Matrix4x3d lookAlong(double dirX, double dirY, double dirZ, 6762 double upX, double upY, double upZ) return { 6763 lookAlong(dirX, dirY, dirZ, upX, upY, upZ, this); 6764 return this; 6765 } 6766 6767 /** 6768 * Set this matrix to a rotation transformation to make <code>-z</code> 6769 * point along <code>dir</code>. 6770 * <p> 6771 * This is equivalent to calling 6772 * {@link #setLookAt(Vector3d, Vector3d, Vector3d) setLookAt()} 6773 * with <code>eye = (0, 0, 0)</code> and <code>center = dir</code>. 6774 * <p> 6775 * In order to apply the lookalong transformation to any previous existing transformation, 6776 * use {@link #lookAlong(Vector3d, Vector3d)}. 6777 * 6778 * @see #setLookAlong(Vector3d, Vector3d) 6779 * @see #lookAlong(Vector3d, Vector3d) 6780 * 6781 * @param dir 6782 * the direction in space to look along 6783 * @param up 6784 * the direction of 'up' 6785 * @return this 6786 */ 6787 ref public Matrix4x3d setLookAlong(ref Vector3d dir, Vector3d up) return { 6788 return setLookAlong(dir.x, dir.y, dir.z, up.x, up.y, up.z); 6789 } 6790 6791 /** 6792 * Set this matrix to a rotation transformation to make <code>-z</code> 6793 * point along <code>dir</code>. 6794 * <p> 6795 * This is equivalent to calling 6796 * {@link #setLookAt(double, double, double, double, double, double, double, double, double) 6797 * setLookAt()} with <code>eye = (0, 0, 0)</code> and <code>center = dir</code>. 6798 * <p> 6799 * In order to apply the lookalong transformation to any previous existing transformation, 6800 * use {@link #lookAlong(double, double, double, double, double, double) lookAlong()} 6801 * 6802 * @see #setLookAlong(double, double, double, double, double, double) 6803 * @see #lookAlong(double, double, double, double, double, double) 6804 * 6805 * @param dirX 6806 * the x-coordinate of the direction to look along 6807 * @param dirY 6808 * the y-coordinate of the direction to look along 6809 * @param dirZ 6810 * the z-coordinate of the direction to look along 6811 * @param upX 6812 * the x-coordinate of the up vector 6813 * @param upY 6814 * the y-coordinate of the up vector 6815 * @param upZ 6816 * the z-coordinate of the up vector 6817 * @return this 6818 */ 6819 ref public Matrix4x3d setLookAlong(double dirX, double dirY, double dirZ, 6820 double upX, double upY, double upZ) return { 6821 // Normalize direction 6822 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 6823 dirX *= -invDirLength; 6824 dirY *= -invDirLength; 6825 dirZ *= -invDirLength; 6826 // left = up x direction 6827 double leftX, leftY, leftZ; 6828 leftX = upY * dirZ - upZ * dirY; 6829 leftY = upZ * dirX - upX * dirZ; 6830 leftZ = upX * dirY - upY * dirX; 6831 // normalize left 6832 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 6833 leftX *= invLeftLength; 6834 leftY *= invLeftLength; 6835 leftZ *= invLeftLength; 6836 // up = direction x left 6837 double upnX = dirY * leftZ - dirZ * leftY; 6838 double upnY = dirZ * leftX - dirX * leftZ; 6839 double upnZ = dirX * leftY - dirY * leftX; 6840 6841 m00 = leftX; 6842 m01 = upnX; 6843 m02 = dirX; 6844 m10 = leftY; 6845 m11 = upnY; 6846 m12 = dirY; 6847 m20 = leftZ; 6848 m21 = upnZ; 6849 m22 = dirZ; 6850 m30 = 0.0; 6851 m31 = 0.0; 6852 m32 = 0.0; 6853 properties = PROPERTY_ORTHONORMAL; 6854 6855 return this; 6856 } 6857 6858 /** 6859 * Set this matrix to be a "lookat" transformation for a right-handed coordinate system, that aligns 6860 * <code>-z</code> with <code>center - eye</code>. 6861 * <p> 6862 * In order to not make use of vectors to specify <code>eye</code>, <code>center</code> and <code>up</code> but use primitives, 6863 * like in the GLU function, use {@link #setLookAt(double, double, double, double, double, double, double, double, double) setLookAt()} 6864 * instead. 6865 * <p> 6866 * In order to apply the lookat transformation to a previous existing transformation, 6867 * use {@link #lookAt(Vector3d, Vector3d, Vector3d) lookAt()}. 6868 * 6869 * @see #setLookAt(double, double, double, double, double, double, double, double, double) 6870 * @see #lookAt(Vector3d, Vector3d, Vector3d) 6871 * 6872 * @param eye 6873 * the position of the camera 6874 * @param center 6875 * the point in space to look at 6876 * @param up 6877 * the direction of 'up' 6878 * @return this 6879 */ 6880 ref public Matrix4x3d setLookAt(Vector3d eye, Vector3d center, Vector3d up) return { 6881 return setLookAt(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z); 6882 } 6883 6884 /** 6885 * Set this matrix to be a "lookat" transformation for a right-handed coordinate system, 6886 * that aligns <code>-z</code> with <code>center - eye</code>. 6887 * <p> 6888 * In order to apply the lookat transformation to a previous existing transformation, 6889 * use {@link #lookAt(double, double, double, double, double, double, double, double, double) lookAt}. 6890 * 6891 * @see #setLookAt(Vector3d, Vector3d, Vector3d) 6892 * @see #lookAt(double, double, double, double, double, double, double, double, double) 6893 * 6894 * @param eyeX 6895 * the x-coordinate of the eye/camera location 6896 * @param eyeY 6897 * the y-coordinate of the eye/camera location 6898 * @param eyeZ 6899 * the z-coordinate of the eye/camera location 6900 * @param centerX 6901 * the x-coordinate of the point to look at 6902 * @param centerY 6903 * the y-coordinate of the point to look at 6904 * @param centerZ 6905 * the z-coordinate of the point to look at 6906 * @param upX 6907 * the x-coordinate of the up vector 6908 * @param upY 6909 * the y-coordinate of the up vector 6910 * @param upZ 6911 * the z-coordinate of the up vector 6912 * @return this 6913 */ 6914 ref public Matrix4x3d setLookAt(double eyeX, double eyeY, double eyeZ, 6915 double centerX, double centerY, double centerZ, 6916 double upX, double upY, double upZ) return { 6917 // Compute direction from position to lookAt 6918 double dirX, dirY, dirZ; 6919 dirX = eyeX - centerX; 6920 dirY = eyeY - centerY; 6921 dirZ = eyeZ - centerZ; 6922 // Normalize direction 6923 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 6924 dirX *= invDirLength; 6925 dirY *= invDirLength; 6926 dirZ *= invDirLength; 6927 // left = up x direction 6928 double leftX, leftY, leftZ; 6929 leftX = upY * dirZ - upZ * dirY; 6930 leftY = upZ * dirX - upX * dirZ; 6931 leftZ = upX * dirY - upY * dirX; 6932 // normalize left 6933 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 6934 leftX *= invLeftLength; 6935 leftY *= invLeftLength; 6936 leftZ *= invLeftLength; 6937 // up = direction x left 6938 double upnX = dirY * leftZ - dirZ * leftY; 6939 double upnY = dirZ * leftX - dirX * leftZ; 6940 double upnZ = dirX * leftY - dirY * leftX; 6941 6942 m00 = leftX; 6943 m01 = upnX; 6944 m02 = dirX; 6945 m10 = leftY; 6946 m11 = upnY; 6947 m12 = dirY; 6948 m20 = leftZ; 6949 m21 = upnZ; 6950 m22 = dirZ; 6951 m30 = -(leftX * eyeX + leftY * eyeY + leftZ * eyeZ); 6952 m31 = -(upnX * eyeX + upnY * eyeY + upnZ * eyeZ); 6953 m32 = -(dirX * eyeX + dirY * eyeY + dirZ * eyeZ); 6954 properties = PROPERTY_ORTHONORMAL; 6955 6956 return this; 6957 } 6958 6959 /** 6960 * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, 6961 * that aligns <code>-z</code> with <code>center - eye</code> and store the result in <code>dest</code>. 6962 * <p> 6963 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 6964 * then the new matrix will be <code>M * L</code>. So when transforming a 6965 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 6966 * the lookat transformation will be applied first! 6967 * <p> 6968 * In order to set the matrix to a lookat transformation without post-multiplying it, 6969 * use {@link #setLookAt(Vector3d, Vector3d, Vector3d)}. 6970 * 6971 * @see #lookAt(double, double, double, double, double, double, double, double, double) 6972 * @see #setLookAlong(Vector3d, Vector3d) 6973 * 6974 * @param eye 6975 * the position of the camera 6976 * @param center 6977 * the point in space to look at 6978 * @param up 6979 * the direction of 'up' 6980 * @param dest 6981 * will hold the result 6982 * @return dest 6983 */ 6984 public Matrix4x3d lookAt(Vector3d eye, Vector3d center, Vector3d up, ref Matrix4x3d dest) { 6985 return lookAt(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z, dest); 6986 } 6987 6988 /** 6989 * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, 6990 * that aligns <code>-z</code> with <code>center - eye</code>. 6991 * <p> 6992 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 6993 * then the new matrix will be <code>M * L</code>. So when transforming a 6994 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 6995 * the lookat transformation will be applied first! 6996 * <p> 6997 * In order to set the matrix to a lookat transformation without post-multiplying it, 6998 * use {@link #setLookAt(Vector3d, Vector3d, Vector3d)}. 6999 * 7000 * @see #lookAt(double, double, double, double, double, double, double, double, double) 7001 * @see #setLookAlong(Vector3d, Vector3d) 7002 * 7003 * @param eye 7004 * the position of the camera 7005 * @param center 7006 * the point in space to look at 7007 * @param up 7008 * the direction of 'up' 7009 * @return this 7010 */ 7011 ref public Matrix4x3d lookAt(Vector3d eye, Vector3d center, Vector3d up) return { 7012 lookAt(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z, this); 7013 return this; 7014 } 7015 7016 /** 7017 * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, 7018 * that aligns <code>-z</code> with <code>center - eye</code> and store the result in <code>dest</code>. 7019 * <p> 7020 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7021 * then the new matrix will be <code>M * L</code>. So when transforming a 7022 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7023 * the lookat transformation will be applied first! 7024 * <p> 7025 * In order to set the matrix to a lookat transformation without post-multiplying it, 7026 * use {@link #setLookAt(double, double, double, double, double, double, double, double, double) setLookAt()}. 7027 * 7028 * @see #lookAt(Vector3d, Vector3d, Vector3d) 7029 * @see #setLookAt(double, double, double, double, double, double, double, double, double) 7030 * 7031 * @param eyeX 7032 * the x-coordinate of the eye/camera location 7033 * @param eyeY 7034 * the y-coordinate of the eye/camera location 7035 * @param eyeZ 7036 * the z-coordinate of the eye/camera location 7037 * @param centerX 7038 * the x-coordinate of the point to look at 7039 * @param centerY 7040 * the y-coordinate of the point to look at 7041 * @param centerZ 7042 * the z-coordinate of the point to look at 7043 * @param upX 7044 * the x-coordinate of the up vector 7045 * @param upY 7046 * the y-coordinate of the up vector 7047 * @param upZ 7048 * the z-coordinate of the up vector 7049 * @param dest 7050 * will hold the result 7051 * @return dest 7052 */ 7053 public Matrix4x3d lookAt(double eyeX, double eyeY, double eyeZ, 7054 double centerX, double centerY, double centerZ, 7055 double upX, double upY, double upZ, ref Matrix4x3d dest) { 7056 if ((properties & PROPERTY_IDENTITY) != 0) 7057 return dest.setLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); 7058 return lookAtGeneric(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, dest); 7059 } 7060 private Matrix4x3d lookAtGeneric(double eyeX, double eyeY, double eyeZ, 7061 double centerX, double centerY, double centerZ, 7062 double upX, double upY, double upZ, ref Matrix4x3d dest) { 7063 // Compute direction from position to lookAt 7064 double dirX, dirY, dirZ; 7065 dirX = eyeX - centerX; 7066 dirY = eyeY - centerY; 7067 dirZ = eyeZ - centerZ; 7068 // Normalize direction 7069 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 7070 dirX *= invDirLength; 7071 dirY *= invDirLength; 7072 dirZ *= invDirLength; 7073 // left = up x direction 7074 double leftX, leftY, leftZ; 7075 leftX = upY * dirZ - upZ * dirY; 7076 leftY = upZ * dirX - upX * dirZ; 7077 leftZ = upX * dirY - upY * dirX; 7078 // normalize left 7079 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 7080 leftX *= invLeftLength; 7081 leftY *= invLeftLength; 7082 leftZ *= invLeftLength; 7083 // up = direction x left 7084 double upnX = dirY * leftZ - dirZ * leftY; 7085 double upnY = dirZ * leftX - dirX * leftZ; 7086 double upnZ = dirX * leftY - dirY * leftX; 7087 7088 // calculate right matrix elements 7089 double rm00 = leftX; 7090 double rm01 = upnX; 7091 double rm02 = dirX; 7092 double rm10 = leftY; 7093 double rm11 = upnY; 7094 double rm12 = dirY; 7095 double rm20 = leftZ; 7096 double rm21 = upnZ; 7097 double rm22 = dirZ; 7098 double rm30 = -(leftX * eyeX + leftY * eyeY + leftZ * eyeZ); 7099 double rm31 = -(upnX * eyeX + upnY * eyeY + upnZ * eyeZ); 7100 double rm32 = -(dirX * eyeX + dirY * eyeY + dirZ * eyeZ); 7101 7102 // perform optimized matrix multiplication 7103 // compute last column first, because others do not depend on it 7104 dest.m30 = m00 * rm30 + m10 * rm31 + m20 * rm32 + m30; 7105 dest.m31 = m01 * rm30 + m11 * rm31 + m21 * rm32 + m31; 7106 dest.m32 = m02 * rm30 + m12 * rm31 + m22 * rm32 + m32; 7107 // introduce temporaries for dependent results 7108 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 7109 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 7110 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 7111 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 7112 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 7113 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 7114 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 7115 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 7116 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 7117 // set the rest of the matrix elements 7118 dest.m00 = nm00; 7119 dest.m01 = nm01; 7120 dest.m02 = nm02; 7121 dest.m10 = nm10; 7122 dest.m11 = nm11; 7123 dest.m12 = nm12; 7124 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 7125 7126 return dest; 7127 } 7128 7129 /** 7130 * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, 7131 * that aligns <code>-z</code> with <code>center - eye</code>. 7132 * <p> 7133 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7134 * then the new matrix will be <code>M * L</code>. So when transforming a 7135 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7136 * the lookat transformation will be applied first! 7137 * <p> 7138 * In order to set the matrix to a lookat transformation without post-multiplying it, 7139 * use {@link #setLookAt(double, double, double, double, double, double, double, double, double) setLookAt()}. 7140 * 7141 * @see #lookAt(Vector3d, Vector3d, Vector3d) 7142 * @see #setLookAt(double, double, double, double, double, double, double, double, double) 7143 * 7144 * @param eyeX 7145 * the x-coordinate of the eye/camera location 7146 * @param eyeY 7147 * the y-coordinate of the eye/camera location 7148 * @param eyeZ 7149 * the z-coordinate of the eye/camera location 7150 * @param centerX 7151 * the x-coordinate of the point to look at 7152 * @param centerY 7153 * the y-coordinate of the point to look at 7154 * @param centerZ 7155 * the z-coordinate of the point to look at 7156 * @param upX 7157 * the x-coordinate of the up vector 7158 * @param upY 7159 * the y-coordinate of the up vector 7160 * @param upZ 7161 * the z-coordinate of the up vector 7162 * @return this 7163 */ 7164 ref public Matrix4x3d lookAt(double eyeX, double eyeY, double eyeZ, 7165 double centerX, double centerY, double centerZ, 7166 double upX, double upY, double upZ) return { 7167 lookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, this); 7168 return this; 7169 } 7170 7171 /** 7172 * Set this matrix to be a "lookat" transformation for a left-handed coordinate system, that aligns 7173 * <code>+z</code> with <code>center - eye</code>. 7174 * <p> 7175 * In order to not make use of vectors to specify <code>eye</code>, <code>center</code> and <code>up</code> but use primitives, 7176 * like in the GLU function, use {@link #setLookAtLH(double, double, double, double, double, double, double, double, double) setLookAtLH()} 7177 * instead. 7178 * <p> 7179 * In order to apply the lookat transformation to a previous existing transformation, 7180 * use {@link #lookAtLH(Vector3d, Vector3d, Vector3d) lookAt()}. 7181 * 7182 * @see #setLookAtLH(double, double, double, double, double, double, double, double, double) 7183 * @see #lookAtLH(Vector3d, Vector3d, Vector3d) 7184 * 7185 * @param eye 7186 * the position of the camera 7187 * @param center 7188 * the point in space to look at 7189 * @param up 7190 * the direction of 'up' 7191 * @return this 7192 */ 7193 ref public Matrix4x3d setLookAtLH(Vector3d eye, Vector3d center, Vector3d up) return { 7194 return setLookAtLH(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z); 7195 } 7196 7197 /** 7198 * Set this matrix to be a "lookat" transformation for a left-handed coordinate system, 7199 * that aligns <code>+z</code> with <code>center - eye</code>. 7200 * <p> 7201 * In order to apply the lookat transformation to a previous existing transformation, 7202 * use {@link #lookAtLH(double, double, double, double, double, double, double, double, double) lookAtLH}. 7203 * 7204 * @see #setLookAtLH(Vector3d, Vector3d, Vector3d) 7205 * @see #lookAtLH(double, double, double, double, double, double, double, double, double) 7206 * 7207 * @param eyeX 7208 * the x-coordinate of the eye/camera location 7209 * @param eyeY 7210 * the y-coordinate of the eye/camera location 7211 * @param eyeZ 7212 * the z-coordinate of the eye/camera location 7213 * @param centerX 7214 * the x-coordinate of the point to look at 7215 * @param centerY 7216 * the y-coordinate of the point to look at 7217 * @param centerZ 7218 * the z-coordinate of the point to look at 7219 * @param upX 7220 * the x-coordinate of the up vector 7221 * @param upY 7222 * the y-coordinate of the up vector 7223 * @param upZ 7224 * the z-coordinate of the up vector 7225 * @return this 7226 */ 7227 ref public Matrix4x3d setLookAtLH(double eyeX, double eyeY, double eyeZ, 7228 double centerX, double centerY, double centerZ, 7229 double upX, double upY, double upZ) return { 7230 // Compute direction from position to lookAt 7231 double dirX, dirY, dirZ; 7232 dirX = centerX - eyeX; 7233 dirY = centerY - eyeY; 7234 dirZ = centerZ - eyeZ; 7235 // Normalize direction 7236 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 7237 dirX *= invDirLength; 7238 dirY *= invDirLength; 7239 dirZ *= invDirLength; 7240 // left = up x direction 7241 double leftX, leftY, leftZ; 7242 leftX = upY * dirZ - upZ * dirY; 7243 leftY = upZ * dirX - upX * dirZ; 7244 leftZ = upX * dirY - upY * dirX; 7245 // normalize left 7246 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 7247 leftX *= invLeftLength; 7248 leftY *= invLeftLength; 7249 leftZ *= invLeftLength; 7250 // up = direction x left 7251 double upnX = dirY * leftZ - dirZ * leftY; 7252 double upnY = dirZ * leftX - dirX * leftZ; 7253 double upnZ = dirX * leftY - dirY * leftX; 7254 7255 m00 = leftX; 7256 m01 = upnX; 7257 m02 = dirX; 7258 m10 = leftY; 7259 m11 = upnY; 7260 m12 = dirY; 7261 m20 = leftZ; 7262 m21 = upnZ; 7263 m22 = dirZ; 7264 m30 = -(leftX * eyeX + leftY * eyeY + leftZ * eyeZ); 7265 m31 = -(upnX * eyeX + upnY * eyeY + upnZ * eyeZ); 7266 m32 = -(dirX * eyeX + dirY * eyeY + dirZ * eyeZ); 7267 properties = PROPERTY_ORTHONORMAL; 7268 7269 return this; 7270 } 7271 7272 /** 7273 * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, 7274 * that aligns <code>+z</code> with <code>center - eye</code> and store the result in <code>dest</code>. 7275 * <p> 7276 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7277 * then the new matrix will be <code>M * L</code>. So when transforming a 7278 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7279 * the lookat transformation will be applied first! 7280 * <p> 7281 * In order to set the matrix to a lookat transformation without post-multiplying it, 7282 * use {@link #setLookAtLH(Vector3d, Vector3d, Vector3d)}. 7283 * 7284 * @see #lookAtLH(double, double, double, double, double, double, double, double, double) 7285 * 7286 * @param eye 7287 * the position of the camera 7288 * @param center 7289 * the point in space to look at 7290 * @param up 7291 * the direction of 'up' 7292 * @param dest 7293 * will hold the result 7294 * @return dest 7295 */ 7296 public Matrix4x3d lookAtLH(Vector3d eye, Vector3d center, Vector3d up, ref Matrix4x3d dest) { 7297 return lookAtLH(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z, dest); 7298 } 7299 7300 /** 7301 * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, 7302 * that aligns <code>+z</code> with <code>center - eye</code>. 7303 * <p> 7304 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7305 * then the new matrix will be <code>M * L</code>. So when transforming a 7306 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7307 * the lookat transformation will be applied first! 7308 * <p> 7309 * In order to set the matrix to a lookat transformation without post-multiplying it, 7310 * use {@link #setLookAtLH(Vector3d, Vector3d, Vector3d)}. 7311 * 7312 * @see #lookAtLH(double, double, double, double, double, double, double, double, double) 7313 * 7314 * @param eye 7315 * the position of the camera 7316 * @param center 7317 * the point in space to look at 7318 * @param up 7319 * the direction of 'up' 7320 * @return this 7321 */ 7322 ref public Matrix4x3d lookAtLH(Vector3d eye, Vector3d center, Vector3d up) return { 7323 lookAtLH(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z, this); 7324 return this; 7325 } 7326 7327 /** 7328 * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, 7329 * that aligns <code>+z</code> with <code>center - eye</code> and store the result in <code>dest</code>. 7330 * <p> 7331 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7332 * then the new matrix will be <code>M * L</code>. So when transforming a 7333 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7334 * the lookat transformation will be applied first! 7335 * <p> 7336 * In order to set the matrix to a lookat transformation without post-multiplying it, 7337 * use {@link #setLookAtLH(double, double, double, double, double, double, double, double, double) setLookAtLH()}. 7338 * 7339 * @see #lookAtLH(Vector3d, Vector3d, Vector3d) 7340 * @see #setLookAtLH(double, double, double, double, double, double, double, double, double) 7341 * 7342 * @param eyeX 7343 * the x-coordinate of the eye/camera location 7344 * @param eyeY 7345 * the y-coordinate of the eye/camera location 7346 * @param eyeZ 7347 * the z-coordinate of the eye/camera location 7348 * @param centerX 7349 * the x-coordinate of the point to look at 7350 * @param centerY 7351 * the y-coordinate of the point to look at 7352 * @param centerZ 7353 * the z-coordinate of the point to look at 7354 * @param upX 7355 * the x-coordinate of the up vector 7356 * @param upY 7357 * the y-coordinate of the up vector 7358 * @param upZ 7359 * the z-coordinate of the up vector 7360 * @param dest 7361 * will hold the result 7362 * @return dest 7363 */ 7364 public Matrix4x3d lookAtLH(double eyeX, double eyeY, double eyeZ, 7365 double centerX, double centerY, double centerZ, 7366 double upX, double upY, double upZ, ref Matrix4x3d dest) { 7367 if ((properties & PROPERTY_IDENTITY) != 0) 7368 return dest.setLookAtLH(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); 7369 return lookAtLHGeneric(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, dest); 7370 } 7371 private Matrix4x3d lookAtLHGeneric(double eyeX, double eyeY, double eyeZ, 7372 double centerX, double centerY, double centerZ, 7373 double upX, double upY, double upZ, ref Matrix4x3d dest) { 7374 // Compute direction from position to lookAt 7375 double dirX, dirY, dirZ; 7376 dirX = centerX - eyeX; 7377 dirY = centerY - eyeY; 7378 dirZ = centerZ - eyeZ; 7379 // Normalize direction 7380 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 7381 dirX *= invDirLength; 7382 dirY *= invDirLength; 7383 dirZ *= invDirLength; 7384 // left = up x direction 7385 double leftX, leftY, leftZ; 7386 leftX = upY * dirZ - upZ * dirY; 7387 leftY = upZ * dirX - upX * dirZ; 7388 leftZ = upX * dirY - upY * dirX; 7389 // normalize left 7390 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 7391 leftX *= invLeftLength; 7392 leftY *= invLeftLength; 7393 leftZ *= invLeftLength; 7394 // up = direction x left 7395 double upnX = dirY * leftZ - dirZ * leftY; 7396 double upnY = dirZ * leftX - dirX * leftZ; 7397 double upnZ = dirX * leftY - dirY * leftX; 7398 7399 // calculate right matrix elements 7400 double rm00 = leftX; 7401 double rm01 = upnX; 7402 double rm02 = dirX; 7403 double rm10 = leftY; 7404 double rm11 = upnY; 7405 double rm12 = dirY; 7406 double rm20 = leftZ; 7407 double rm21 = upnZ; 7408 double rm22 = dirZ; 7409 double rm30 = -(leftX * eyeX + leftY * eyeY + leftZ * eyeZ); 7410 double rm31 = -(upnX * eyeX + upnY * eyeY + upnZ * eyeZ); 7411 double rm32 = -(dirX * eyeX + dirY * eyeY + dirZ * eyeZ); 7412 7413 // perform optimized matrix multiplication 7414 // compute last column first, because others do not depend on it 7415 dest.m30 = m00 * rm30 + m10 * rm31 + m20 * rm32 + m30; 7416 dest.m31 = m01 * rm30 + m11 * rm31 + m21 * rm32 + m31; 7417 dest.m32 = m02 * rm30 + m12 * rm31 + m22 * rm32 + m32; 7418 // introduce temporaries for dependent results 7419 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 7420 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 7421 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 7422 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 7423 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 7424 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 7425 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 7426 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 7427 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 7428 // set the rest of the matrix elements 7429 dest.m00 = nm00; 7430 dest.m01 = nm01; 7431 dest.m02 = nm02; 7432 dest.m10 = nm10; 7433 dest.m11 = nm11; 7434 dest.m12 = nm12; 7435 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 7436 7437 return dest; 7438 } 7439 7440 /** 7441 * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, 7442 * that aligns <code>+z</code> with <code>center - eye</code>. 7443 * <p> 7444 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7445 * then the new matrix will be <code>M * L</code>. So when transforming a 7446 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7447 * the lookat transformation will be applied first! 7448 * <p> 7449 * In order to set the matrix to a lookat transformation without post-multiplying it, 7450 * use {@link #setLookAtLH(double, double, double, double, double, double, double, double, double) setLookAtLH()}. 7451 * 7452 * @see #lookAtLH(Vector3d, Vector3d, Vector3d) 7453 * @see #setLookAtLH(double, double, double, double, double, double, double, double, double) 7454 * 7455 * @param eyeX 7456 * the x-coordinate of the eye/camera location 7457 * @param eyeY 7458 * the y-coordinate of the eye/camera location 7459 * @param eyeZ 7460 * the z-coordinate of the eye/camera location 7461 * @param centerX 7462 * the x-coordinate of the point to look at 7463 * @param centerY 7464 * the y-coordinate of the point to look at 7465 * @param centerZ 7466 * the z-coordinate of the point to look at 7467 * @param upX 7468 * the x-coordinate of the up vector 7469 * @param upY 7470 * the y-coordinate of the up vector 7471 * @param upZ 7472 * the z-coordinate of the up vector 7473 * @return this 7474 */ 7475 ref public Matrix4x3d lookAtLH(double eyeX, double eyeY, double eyeZ, 7476 double centerX, double centerY, double centerZ, 7477 double upX, double upY, double upZ) return { 7478 lookAtLH(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, this); 7479 return this; 7480 } 7481 7482 public Vector4d frustumPlane(int which, Vector4d dest) { 7483 switch (which) { 7484 case PLANE_NX: 7485 dest.set(m00, m10, m20, 1.0 + m30).normalize(); 7486 break; 7487 case PLANE_PX: 7488 dest.set(-m00, -m10, -m20, 1.0 - m30).normalize(); 7489 break; 7490 case PLANE_NY: 7491 dest.set(m01, m11, m21, 1.0 + m31).normalize(); 7492 break; 7493 case PLANE_PY: 7494 dest.set(-m01, -m11, -m21, 1.0 - m31).normalize(); 7495 break; 7496 case PLANE_NZ: 7497 dest.set(m02, m12, m22, 1.0 + m32).normalize(); 7498 break; 7499 case PLANE_PZ: 7500 dest.set(-m02, -m12, -m22, 1.0 - m32).normalize(); 7501 break; 7502 default: 7503 // do nothing 7504 } 7505 return dest; 7506 } 7507 7508 public Vector3d positiveZ(ref Vector3d dir) { 7509 dir.x = m10 * m21 - m11 * m20; 7510 dir.y = m20 * m01 - m21 * m00; 7511 dir.z = m00 * m11 - m01 * m10; 7512 return dir.normalize(dir); 7513 } 7514 7515 public Vector3d normalizedPositiveZ(ref Vector3d dir) { 7516 dir.x = m02; 7517 dir.y = m12; 7518 dir.z = m22; 7519 return dir; 7520 } 7521 7522 public Vector3d positiveX(ref Vector3d dir) { 7523 dir.x = m11 * m22 - m12 * m21; 7524 dir.y = m02 * m21 - m01 * m22; 7525 dir.z = m01 * m12 - m02 * m11; 7526 return dir.normalize(dir); 7527 } 7528 7529 public Vector3d normalizedPositiveX(ref Vector3d dir) { 7530 dir.x = m00; 7531 dir.y = m10; 7532 dir.z = m20; 7533 return dir; 7534 } 7535 7536 public Vector3d positiveY(ref Vector3d dir) { 7537 dir.x = m12 * m20 - m10 * m22; 7538 dir.y = m00 * m22 - m02 * m20; 7539 dir.z = m02 * m10 - m00 * m12; 7540 return dir.normalize(dir); 7541 } 7542 7543 public Vector3d normalizedPositiveY(ref Vector3d dir) { 7544 dir.x = m01; 7545 dir.y = m11; 7546 dir.z = m21; 7547 return dir; 7548 } 7549 7550 public Vector3d origin(Vector3d origin) { 7551 double a = m00 * m11 - m01 * m10; 7552 double b = m00 * m12 - m02 * m10; 7553 double d = m01 * m12 - m02 * m11; 7554 double g = m20 * m31 - m21 * m30; 7555 double h = m20 * m32 - m22 * m30; 7556 double j = m21 * m32 - m22 * m31; 7557 origin.x = -m10 * j + m11 * h - m12 * g; 7558 origin.y = m00 * j - m01 * h + m02 * g; 7559 origin.z = -m30 * d + m31 * b - m32 * a; 7560 return origin; 7561 } 7562 7563 /** 7564 * Apply a projection transformation to this matrix that projects onto the plane specified via the general plane equation 7565 * <code>x*a + y*b + z*c + d = 0</code> as if casting a shadow from a given light position/direction <code>light</code>. 7566 * <p> 7567 * 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. 7568 * <p> 7569 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the shadow matrix, 7570 * then the new matrix will be <code>M * S</code>. So when transforming a 7571 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 7572 * shadow projection will be applied first! 7573 * <p> 7574 * Reference: <a href="ftp://ftp.sgi.com/opengl/contrib/blythe/advanced99/notes/node192.html">ftp.sgi.com</a> 7575 * 7576 * @param light 7577 * the light's vector 7578 * @param a 7579 * the x factor in the plane equation 7580 * @param b 7581 * the y factor in the plane equation 7582 * @param c 7583 * the z factor in the plane equation 7584 * @param d 7585 * the constant in the plane equation 7586 * @return this 7587 */ 7588 ref public Matrix4x3d shadow(Vector4d light, double a, double b, double c, double d) return { 7589 shadow(light.x, light.y, light.z, light.w, a, b, c, d, this); 7590 return this; 7591 } 7592 7593 public Matrix4x3d shadow(Vector4d light, double a, double b, double c, double d, ref Matrix4x3d dest) { 7594 return shadow(light.x, light.y, light.z, light.w, a, b, c, d, dest); 7595 } 7596 7597 /** 7598 * Apply a projection transformation to this matrix that projects onto the plane specified via the general plane equation 7599 * <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>. 7600 * <p> 7601 * 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. 7602 * <p> 7603 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the shadow matrix, 7604 * then the new matrix will be <code>M * S</code>. So when transforming a 7605 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 7606 * shadow projection will be applied first! 7607 * <p> 7608 * Reference: <a href="ftp://ftp.sgi.com/opengl/contrib/blythe/advanced99/notes/node192.html">ftp.sgi.com</a> 7609 * 7610 * @param lightX 7611 * the x-component of the light's vector 7612 * @param lightY 7613 * the y-component of the light's vector 7614 * @param lightZ 7615 * the z-component of the light's vector 7616 * @param lightW 7617 * the w-component of the light's vector 7618 * @param a 7619 * the x factor in the plane equation 7620 * @param b 7621 * the y factor in the plane equation 7622 * @param c 7623 * the z factor in the plane equation 7624 * @param d 7625 * the constant in the plane equation 7626 * @return this 7627 */ 7628 ref public Matrix4x3d shadow(double lightX, double lightY, double lightZ, double lightW, double a, double b, double c, double d) return { 7629 shadow(lightX, lightY, lightZ, lightW, a, b, c, d, this); 7630 return this; 7631 } 7632 7633 public Matrix4x3d shadow(double lightX, double lightY, double lightZ, double lightW, double a, double b, double c, double d, ref Matrix4x3d dest) { 7634 // normalize plane 7635 double invPlaneLen = Math.invsqrt(a*a + b*b + c*c); 7636 double an = a * invPlaneLen; 7637 double bn = b * invPlaneLen; 7638 double cn = c * invPlaneLen; 7639 double dn = d * invPlaneLen; 7640 7641 double dot = an * lightX + bn * lightY + cn * lightZ + dn * lightW; 7642 7643 // compute right matrix elements 7644 double rm00 = dot - an * lightX; 7645 double rm01 = -an * lightY; 7646 double rm02 = -an * lightZ; 7647 double rm03 = -an * lightW; 7648 double rm10 = -bn * lightX; 7649 double rm11 = dot - bn * lightY; 7650 double rm12 = -bn * lightZ; 7651 double rm13 = -bn * lightW; 7652 double rm20 = -cn * lightX; 7653 double rm21 = -cn * lightY; 7654 double rm22 = dot - cn * lightZ; 7655 double rm23 = -cn * lightW; 7656 double rm30 = -dn * lightX; 7657 double rm31 = -dn * lightY; 7658 double rm32 = -dn * lightZ; 7659 double rm33 = dot - dn * lightW; 7660 7661 // matrix multiplication 7662 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02 + m30 * rm03; 7663 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02 + m31 * rm03; 7664 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02 + m32 * rm03; 7665 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12 + m30 * rm13; 7666 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12 + m31 * rm13; 7667 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12 + m32 * rm13; 7668 double nm20 = m00 * rm20 + m10 * rm21 + m20 * rm22 + m30 * rm23; 7669 double nm21 = m01 * rm20 + m11 * rm21 + m21 * rm22 + m31 * rm23; 7670 double nm22 = m02 * rm20 + m12 * rm21 + m22 * rm22 + m32 * rm23; 7671 dest.m30 = m00 * rm30 + m10 * rm31 + m20 * rm32 + m30 * rm33; 7672 dest.m31 = m01 * rm30 + m11 * rm31 + m21 * rm32 + m31 * rm33; 7673 dest.m32 = m02 * rm30 + m12 * rm31 + m22 * rm32 + m32 * rm33; 7674 dest.m00 = nm00; 7675 dest.m01 = nm01; 7676 dest.m02 = nm02; 7677 dest.m10 = nm10; 7678 dest.m11 = nm11; 7679 dest.m12 = nm12; 7680 dest.m20 = nm20; 7681 dest.m21 = nm21; 7682 dest.m22 = nm22; 7683 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 7684 7685 return dest; 7686 } 7687 7688 public Matrix4x3d shadow(Vector4d light, Matrix4x3d planeTransform, ref Matrix4x3d dest) { 7689 // compute plane equation by transforming (y = 0) 7690 double a = planeTransform.m10; 7691 double b = planeTransform.m11; 7692 double c = planeTransform.m12; 7693 double d = -a * planeTransform.m30 - b * planeTransform.m31 - c * planeTransform.m32; 7694 return shadow(light.x, light.y, light.z, light.w, a, b, c, d, dest); 7695 } 7696 7697 /** 7698 * Apply a projection transformation to this matrix that projects onto the plane with the general plane equation 7699 * <code>y = 0</code> as if casting a shadow from a given light position/direction <code>light</code>. 7700 * <p> 7701 * Before the shadow projection is applied, the plane is transformed via the specified <code>planeTransformation</code>. 7702 * <p> 7703 * 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. 7704 * <p> 7705 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the shadow matrix, 7706 * then the new matrix will be <code>M * S</code>. So when transforming a 7707 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 7708 * shadow projection will be applied first! 7709 * 7710 * @param light 7711 * the light's vector 7712 * @param planeTransform 7713 * the transformation to transform the implied plane <code>y = 0</code> before applying the projection 7714 * @return this 7715 */ 7716 ref public Matrix4x3d shadow(Vector4d light, Matrix4x3d planeTransform) return { 7717 shadow(light, planeTransform, this); 7718 return this; 7719 } 7720 7721 public Matrix4x3d shadow(double lightX, double lightY, double lightZ, double lightW, Matrix4x3d planeTransform, ref Matrix4x3d dest) { 7722 // compute plane equation by transforming (y = 0) 7723 double a = planeTransform.m10; 7724 double b = planeTransform.m11; 7725 double c = planeTransform.m12; 7726 double d = -a * planeTransform.m30 - b * planeTransform.m31 - c * planeTransform.m32; 7727 return shadow(lightX, lightY, lightZ, lightW, a, b, c, d, dest); 7728 } 7729 7730 /** 7731 * Apply a projection transformation to this matrix that projects onto the plane with the general plane equation 7732 * <code>y = 0</code> as if casting a shadow from a given light position/direction <code>(lightX, lightY, lightZ, lightW)</code>. 7733 * <p> 7734 * Before the shadow projection is applied, the plane is transformed via the specified <code>planeTransformation</code>. 7735 * <p> 7736 * 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. 7737 * <p> 7738 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the shadow matrix, 7739 * then the new matrix will be <code>M * S</code>. So when transforming a 7740 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 7741 * shadow projection will be applied first! 7742 * 7743 * @param lightX 7744 * the x-component of the light vector 7745 * @param lightY 7746 * the y-component of the light vector 7747 * @param lightZ 7748 * the z-component of the light vector 7749 * @param lightW 7750 * the w-component of the light vector 7751 * @param planeTransform 7752 * the transformation to transform the implied plane <code>y = 0</code> before applying the projection 7753 * @return this 7754 */ 7755 ref public Matrix4x3d shadow(double lightX, double lightY, double lightZ, double lightW, Matrix4x3d planeTransform) return { 7756 shadow(lightX, lightY, lightZ, lightW, planeTransform, this); 7757 return this; 7758 } 7759 7760 /** 7761 * Set this matrix to a cylindrical billboard transformation that rotates the local +Z axis of a given object with position <code>objPos</code> towards 7762 * a target position at <code>targetPos</code> while constraining a cylindrical rotation around the given <code>up</code> vector. 7763 * <p> 7764 * This method can be used to create the complete model transformation for a given object, including the translation of the object to 7765 * its position <code>objPos</code>. 7766 * 7767 * @param objPos 7768 * the position of the object to rotate towards <code>targetPos</code> 7769 * @param targetPos 7770 * the position of the target (for example the camera) towards which to rotate the object 7771 * @param up 7772 * the rotation axis (must be {@link Vector3d#normalize() normalized}) 7773 * @return this 7774 */ 7775 ref public Matrix4x3d billboardCylindrical(Vector3d objPos, Vector3d targetPos, Vector3d up) return { 7776 double dirX = targetPos.x - objPos.x; 7777 double dirY = targetPos.y - objPos.y; 7778 double dirZ = targetPos.z - objPos.z; 7779 // left = up x dir 7780 double leftX = up.y * dirZ - up.z * dirY; 7781 double leftY = up.z * dirX - up.x * dirZ; 7782 double leftZ = up.x * dirY - up.y * dirX; 7783 // normalize left 7784 double invLeftLen = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 7785 leftX *= invLeftLen; 7786 leftY *= invLeftLen; 7787 leftZ *= invLeftLen; 7788 // recompute dir by constraining rotation around 'up' 7789 // dir = left x up 7790 dirX = leftY * up.z - leftZ * up.y; 7791 dirY = leftZ * up.x - leftX * up.z; 7792 dirZ = leftX * up.y - leftY * up.x; 7793 // normalize dir 7794 double invDirLen = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 7795 dirX *= invDirLen; 7796 dirY *= invDirLen; 7797 dirZ *= invDirLen; 7798 // set matrix elements 7799 m00 = leftX; 7800 m01 = leftY; 7801 m02 = leftZ; 7802 m10 = up.x; 7803 m11 = up.y; 7804 m12 = up.z; 7805 m20 = dirX; 7806 m21 = dirY; 7807 m22 = dirZ; 7808 m30 = objPos.x; 7809 m31 = objPos.y; 7810 m32 = objPos.z; 7811 properties = PROPERTY_ORTHONORMAL; 7812 return this; 7813 } 7814 7815 /** 7816 * Set this matrix to a spherical billboard transformation that rotates the local +Z axis of a given object with position <code>objPos</code> towards 7817 * a target position at <code>targetPos</code>. 7818 * <p> 7819 * This method can be used to create the complete model transformation for a given object, including the translation of the object to 7820 * its position <code>objPos</code>. 7821 * <p> 7822 * If preserving an <i>up</i> vector is not necessary when rotating the +Z axis, then a shortest arc rotation can be obtained 7823 * using {@link #billboardSpherical(Vector3d, Vector3d)}. 7824 * 7825 * @see #billboardSpherical(Vector3d, Vector3d) 7826 * 7827 * @param objPos 7828 * the position of the object to rotate towards <code>targetPos</code> 7829 * @param targetPos 7830 * the position of the target (for example the camera) towards which to rotate the object 7831 * @param up 7832 * the up axis used to orient the object 7833 * @return this 7834 */ 7835 ref public Matrix4x3d billboardSpherical(Vector3d objPos, Vector3d targetPos, Vector3d up) return { 7836 double dirX = targetPos.x - objPos.x; 7837 double dirY = targetPos.y - objPos.y; 7838 double dirZ = targetPos.z - objPos.z; 7839 // normalize dir 7840 double invDirLen = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 7841 dirX *= invDirLen; 7842 dirY *= invDirLen; 7843 dirZ *= invDirLen; 7844 // left = up x dir 7845 double leftX = up.y * dirZ - up.z * dirY; 7846 double leftY = up.z * dirX - up.x * dirZ; 7847 double leftZ = up.x * dirY - up.y * dirX; 7848 // normalize left 7849 double invLeftLen = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 7850 leftX *= invLeftLen; 7851 leftY *= invLeftLen; 7852 leftZ *= invLeftLen; 7853 // up = dir x left 7854 double upX = dirY * leftZ - dirZ * leftY; 7855 double upY = dirZ * leftX - dirX * leftZ; 7856 double upZ = dirX * leftY - dirY * leftX; 7857 // set matrix elements 7858 m00 = leftX; 7859 m01 = leftY; 7860 m02 = leftZ; 7861 m10 = upX; 7862 m11 = upY; 7863 m12 = upZ; 7864 m20 = dirX; 7865 m21 = dirY; 7866 m22 = dirZ; 7867 m30 = objPos.x; 7868 m31 = objPos.y; 7869 m32 = objPos.z; 7870 properties = PROPERTY_ORTHONORMAL; 7871 return this; 7872 } 7873 7874 /** 7875 * Set this matrix to a spherical billboard transformation that rotates the local +Z axis of a given object with position <code>objPos</code> towards 7876 * a target position at <code>targetPos</code> using a shortest arc rotation by not preserving any <i>up</i> vector of the object. 7877 * <p> 7878 * This method can be used to create the complete model transformation for a given object, including the translation of the object to 7879 * its position <code>objPos</code>. 7880 * <p> 7881 * In order to specify an <i>up</i> vector which needs to be maintained when rotating the +Z axis of the object, 7882 * use {@link #billboardSpherical(Vector3d, Vector3d, Vector3d)}. 7883 * 7884 * @see #billboardSpherical(Vector3d, Vector3d, Vector3d) 7885 * 7886 * @param objPos 7887 * the position of the object to rotate towards <code>targetPos</code> 7888 * @param targetPos 7889 * the position of the target (for example the camera) towards which to rotate the object 7890 * @return this 7891 */ 7892 ref public Matrix4x3d billboardSpherical(Vector3d objPos, Vector3d targetPos) return { 7893 double toDirX = targetPos.x - objPos.x; 7894 double toDirY = targetPos.y - objPos.y; 7895 double toDirZ = targetPos.z - objPos.z; 7896 double x = -toDirY; 7897 double y = toDirX; 7898 double w = Math.sqrt(toDirX * toDirX + toDirY * toDirY + toDirZ * toDirZ) + toDirZ; 7899 double invNorm = Math.invsqrt(x * x + y * y + w * w); 7900 x *= invNorm; 7901 y *= invNorm; 7902 w *= invNorm; 7903 double q00 = (x + x) * x; 7904 double q11 = (y + y) * y; 7905 double q01 = (x + x) * y; 7906 double q03 = (x + x) * w; 7907 double q13 = (y + y) * w; 7908 m00 = 1.0 - q11; 7909 m01 = q01; 7910 m02 = -q13; 7911 m10 = q01; 7912 m11 = 1.0 - q00; 7913 m12 = q03; 7914 m20 = q13; 7915 m21 = -q03; 7916 m22 = 1.0 - q11 - q00; 7917 m30 = objPos.x; 7918 m31 = objPos.y; 7919 m32 = objPos.z; 7920 properties = PROPERTY_ORTHONORMAL; 7921 return this; 7922 } 7923 7924 public int hashCode() { 7925 immutable int prime = 31; 7926 int result = 1; 7927 long temp; 7928 temp = Math.doubleToLongBits(m00); 7929 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7930 temp = Math.doubleToLongBits(m01); 7931 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7932 temp = Math.doubleToLongBits(m02); 7933 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7934 temp = Math.doubleToLongBits(m10); 7935 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7936 temp = Math.doubleToLongBits(m11); 7937 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7938 temp = Math.doubleToLongBits(m12); 7939 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7940 temp = Math.doubleToLongBits(m20); 7941 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7942 temp = Math.doubleToLongBits(m21); 7943 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7944 temp = Math.doubleToLongBits(m22); 7945 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7946 temp = Math.doubleToLongBits(m30); 7947 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7948 temp = Math.doubleToLongBits(m31); 7949 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7950 temp = Math.doubleToLongBits(m32); 7951 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7952 return result; 7953 } 7954 7955 public bool equals(Matrix4x3d m, double delta) { 7956 if (this == m) 7957 return true; 7958 if (!Math.equals(m00, m.m00, delta)) 7959 return false; 7960 if (!Math.equals(m01, m.m01, delta)) 7961 return false; 7962 if (!Math.equals(m02, m.m02, delta)) 7963 return false; 7964 if (!Math.equals(m10, m.m10, delta)) 7965 return false; 7966 if (!Math.equals(m11, m.m11, delta)) 7967 return false; 7968 if (!Math.equals(m12, m.m12, delta)) 7969 return false; 7970 if (!Math.equals(m20, m.m20, delta)) 7971 return false; 7972 if (!Math.equals(m21, m.m21, delta)) 7973 return false; 7974 if (!Math.equals(m22, m.m22, delta)) 7975 return false; 7976 if (!Math.equals(m30, m.m30, delta)) 7977 return false; 7978 if (!Math.equals(m31, m.m31, delta)) 7979 return false; 7980 if (!Math.equals(m32, m.m32, delta)) 7981 return false; 7982 return true; 7983 } 7984 7985 public Matrix4x3d pick(double x, double y, double width, double height, int[] viewport, ref Matrix4x3d dest) { 7986 double sx = viewport[2] / width; 7987 double sy = viewport[3] / height; 7988 double tx = (viewport[2] + 2.0 * (viewport[0] - x)) / width; 7989 double ty = (viewport[3] + 2.0 * (viewport[1] - y)) / height; 7990 dest.m30 = m00 * tx + m10 * ty + m30; 7991 dest.m31 = m01 * tx + m11 * ty + m31; 7992 dest.m32 = m02 * tx + m12 * ty + m32; 7993 dest.m00 = m00 * sx; 7994 dest.m01 = m01 * sx; 7995 dest.m02 = m02 * sx; 7996 dest.m10 = m10 * sy; 7997 dest.m11 = m11 * sy; 7998 dest.m12 = m12 * sy; 7999 dest.properties = 0; 8000 return dest; 8001 } 8002 8003 /** 8004 * Apply a picking transformation to this matrix using the given window coordinates <code>(x, y)</code> as the pick center 8005 * and the given <code>(width, height)</code> as the size of the picking region in window coordinates. 8006 * 8007 * @param x 8008 * the x coordinate of the picking region center in window coordinates 8009 * @param y 8010 * the y coordinate of the picking region center in window coordinates 8011 * @param width 8012 * the width of the picking region in window coordinates 8013 * @param height 8014 * the height of the picking region in window coordinates 8015 * @param viewport 8016 * the viewport described by <code>[x, y, width, height]</code> 8017 * @return this 8018 */ 8019 ref public Matrix4x3d pick(double x, double y, double width, double height, int[] viewport) return { 8020 pick(x, y, width, height, viewport, this); 8021 return this; 8022 } 8023 8024 /** 8025 * Exchange the values of <code>this</code> matrix with the given <code>other</code> matrix. 8026 * 8027 * @param other 8028 * the other matrix to exchange the values with 8029 * @return this 8030 */ 8031 ref public Matrix4x3d swap(ref Matrix4x3d other) return { 8032 double tmp; 8033 tmp = m00; m00 = other.m00; other.m00 = tmp; 8034 tmp = m01; m01 = other.m01; other.m01 = tmp; 8035 tmp = m02; m02 = other.m02; other.m02 = tmp; 8036 tmp = m10; m10 = other.m10; other.m10 = tmp; 8037 tmp = m11; m11 = other.m11; other.m11 = tmp; 8038 tmp = m12; m12 = other.m12; other.m12 = tmp; 8039 tmp = m20; m20 = other.m20; other.m20 = tmp; 8040 tmp = m21; m21 = other.m21; other.m21 = tmp; 8041 tmp = m22; m22 = other.m22; other.m22 = tmp; 8042 tmp = m30; m30 = other.m30; other.m30 = tmp; 8043 tmp = m31; m31 = other.m31; other.m31 = tmp; 8044 tmp = m32; m32 = other.m32; other.m32 = tmp; 8045 int props = properties; 8046 this.properties = other.properties; 8047 other.properties = props; 8048 return this; 8049 } 8050 8051 public Matrix4x3d arcball(double radius, double centerX, double centerY, double centerZ, double angleX, double angleY, ref Matrix4x3d dest) { 8052 double m30 = m20 * -radius + this.m30; 8053 double m31 = m21 * -radius + this.m31; 8054 double m32 = m22 * -radius + this.m32; 8055 double sin = Math.sin(angleX); 8056 double cos = Math.cosFromSin(sin, angleX); 8057 double nm10 = m10 * cos + m20 * sin; 8058 double nm11 = m11 * cos + m21 * sin; 8059 double nm12 = m12 * cos + m22 * sin; 8060 double m20 = this.m20 * cos - m10 * sin; 8061 double m21 = this.m21 * cos - m11 * sin; 8062 double m22 = this.m22 * cos - m12 * sin; 8063 sin = Math.sin(angleY); 8064 cos = Math.cosFromSin(sin, angleY); 8065 double nm00 = m00 * cos - m20 * sin; 8066 double nm01 = m01 * cos - m21 * sin; 8067 double nm02 = m02 * cos - m22 * sin; 8068 double nm20 = m00 * sin + m20 * cos; 8069 double nm21 = m01 * sin + m21 * cos; 8070 double nm22 = m02 * sin + m22 * cos; 8071 dest.m30 = -nm00 * centerX - nm10 * centerY - nm20 * centerZ + m30; 8072 dest.m31 = -nm01 * centerX - nm11 * centerY - nm21 * centerZ + m31; 8073 dest.m32 = -nm02 * centerX - nm12 * centerY - nm22 * centerZ + m32; 8074 dest.m20 = nm20; 8075 dest.m21 = nm21; 8076 dest.m22 = nm22; 8077 dest.m10 = nm10; 8078 dest.m11 = nm11; 8079 dest.m12 = nm12; 8080 dest.m00 = nm00; 8081 dest.m01 = nm01; 8082 dest.m02 = nm02; 8083 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 8084 return dest; 8085 } 8086 8087 public Matrix4x3d arcball(double radius, Vector3d center, double angleX, double angleY, ref Matrix4x3d dest) { 8088 return arcball(radius, center.x, center.y, center.z, angleX, angleY, dest); 8089 } 8090 8091 /** 8092 * Apply an arcball view transformation to this matrix with the given <code>radius</code> and center <code>(centerX, centerY, centerZ)</code> 8093 * position of the arcball and the specified X and Y rotation angles. 8094 * <p> 8095 * This method is equivalent to calling: <code>translate(0, 0, -radius).rotateX(angleX).rotateY(angleY).translate(-centerX, -centerY, -centerZ)</code> 8096 * 8097 * @param radius 8098 * the arcball radius 8099 * @param centerX 8100 * the x coordinate of the center position of the arcball 8101 * @param centerY 8102 * the y coordinate of the center position of the arcball 8103 * @param centerZ 8104 * the z coordinate of the center position of the arcball 8105 * @param angleX 8106 * the rotation angle around the X axis in radians 8107 * @param angleY 8108 * the rotation angle around the Y axis in radians 8109 * @return this 8110 */ 8111 ref public Matrix4x3d arcball(double radius, double centerX, double centerY, double centerZ, double angleX, double angleY) return { 8112 arcball(radius, centerX, centerY, centerZ, angleX, angleY, this); 8113 return this; 8114 } 8115 8116 /** 8117 * Apply an arcball view transformation to this matrix with the given <code>radius</code> and <code>center</code> 8118 * position of the arcball and the specified X and Y rotation angles. 8119 * <p> 8120 * This method is equivalent to calling: <code>translate(0, 0, -radius).rotateX(angleX).rotateY(angleY).translate(-center.x, -center.y, -center.z)</code> 8121 * 8122 * @param radius 8123 * the arcball radius 8124 * @param center 8125 * the center position of the arcball 8126 * @param angleX 8127 * the rotation angle around the X axis in radians 8128 * @param angleY 8129 * the rotation angle around the Y axis in radians 8130 * @return this 8131 */ 8132 ref public Matrix4x3d arcball(double radius, Vector3d center, double angleX, double angleY) return { 8133 arcball(radius, center.x, center.y, center.z, angleX, angleY, this); 8134 return this; 8135 } 8136 8137 public Matrix4x3d transformAab(double minX, double minY, double minZ, double maxX, double maxY, double maxZ, Vector3d outMin, Vector3d outMax) { 8138 double xax = m00 * minX, xay = m01 * minX, xaz = m02 * minX; 8139 double xbx = m00 * maxX, xby = m01 * maxX, xbz = m02 * maxX; 8140 double yax = m10 * minY, yay = m11 * minY, yaz = m12 * minY; 8141 double ybx = m10 * maxY, yby = m11 * maxY, ybz = m12 * maxY; 8142 double zax = m20 * minZ, zay = m21 * minZ, zaz = m22 * minZ; 8143 double zbx = m20 * maxZ, zby = m21 * maxZ, zbz = m22 * maxZ; 8144 double xminx, xminy, xminz, yminx, yminy, yminz, zminx, zminy, zminz; 8145 double xmaxx, xmaxy, xmaxz, ymaxx, ymaxy, ymaxz, zmaxx, zmaxy, zmaxz; 8146 if (xax < xbx) { 8147 xminx = xax; 8148 xmaxx = xbx; 8149 } else { 8150 xminx = xbx; 8151 xmaxx = xax; 8152 } 8153 if (xay < xby) { 8154 xminy = xay; 8155 xmaxy = xby; 8156 } else { 8157 xminy = xby; 8158 xmaxy = xay; 8159 } 8160 if (xaz < xbz) { 8161 xminz = xaz; 8162 xmaxz = xbz; 8163 } else { 8164 xminz = xbz; 8165 xmaxz = xaz; 8166 } 8167 if (yax < ybx) { 8168 yminx = yax; 8169 ymaxx = ybx; 8170 } else { 8171 yminx = ybx; 8172 ymaxx = yax; 8173 } 8174 if (yay < yby) { 8175 yminy = yay; 8176 ymaxy = yby; 8177 } else { 8178 yminy = yby; 8179 ymaxy = yay; 8180 } 8181 if (yaz < ybz) { 8182 yminz = yaz; 8183 ymaxz = ybz; 8184 } else { 8185 yminz = ybz; 8186 ymaxz = yaz; 8187 } 8188 if (zax < zbx) { 8189 zminx = zax; 8190 zmaxx = zbx; 8191 } else { 8192 zminx = zbx; 8193 zmaxx = zax; 8194 } 8195 if (zay < zby) { 8196 zminy = zay; 8197 zmaxy = zby; 8198 } else { 8199 zminy = zby; 8200 zmaxy = zay; 8201 } 8202 if (zaz < zbz) { 8203 zminz = zaz; 8204 zmaxz = zbz; 8205 } else { 8206 zminz = zbz; 8207 zmaxz = zaz; 8208 } 8209 outMin.x = xminx + yminx + zminx + m30; 8210 outMin.y = xminy + yminy + zminy + m31; 8211 outMin.z = xminz + yminz + zminz + m32; 8212 outMax.x = xmaxx + ymaxx + zmaxx + m30; 8213 outMax.y = xmaxy + ymaxy + zmaxy + m31; 8214 outMax.z = xmaxz + ymaxz + zmaxz + m32; 8215 return this; 8216 } 8217 8218 public Matrix4x3d transformAab(Vector3d min, Vector3d max, Vector3d outMin, Vector3d outMax) { 8219 return transformAab(min.x, min.y, min.z, max.x, max.y, max.z, outMin, outMax); 8220 } 8221 8222 /** 8223 * Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code> 8224 * and store the result in <code>this</code>. 8225 * <p> 8226 * 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> 8227 * then the result is <code>other</code>. 8228 * 8229 * @param other 8230 * the other matrix 8231 * @param t 8232 * the interpolation factor between 0.0 and 1.0 8233 * @return this 8234 */ 8235 ref public Matrix4x3d lerp(Matrix4x3d other, double t) return { 8236 lerp(other, t, this); 8237 return this; 8238 } 8239 8240 public Matrix4x3d lerp(Matrix4x3d other, double t, ref Matrix4x3d dest) { 8241 dest.m00 = Math.fma(other.m00 - m00, t, m00); 8242 dest.m01 = Math.fma(other.m01 - m01, t, m01); 8243 dest.m02 = Math.fma(other.m02 - m02, t, m02); 8244 dest.m10 = Math.fma(other.m10 - m10, t, m10); 8245 dest.m11 = Math.fma(other.m11 - m11, t, m11); 8246 dest.m12 = Math.fma(other.m12 - m12, t, m12); 8247 dest.m20 = Math.fma(other.m20 - m20, t, m20); 8248 dest.m21 = Math.fma(other.m21 - m21, t, m21); 8249 dest.m22 = Math.fma(other.m22 - m22, t, m22); 8250 dest.m30 = Math.fma(other.m30 - m30, t, m30); 8251 dest.m31 = Math.fma(other.m31 - m31, t, m31); 8252 dest.m32 = Math.fma(other.m32 - m32, t, m32); 8253 dest.properties = properties & other.properties; 8254 return dest; 8255 } 8256 8257 /** 8258 * Apply a model transformation to this matrix for a right-handed coordinate system, 8259 * that aligns the local <code>+Z</code> axis with <code>dir</code> 8260 * and store the result in <code>dest</code>. 8261 * <p> 8262 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 8263 * then the new matrix will be <code>M * L</code>. So when transforming a 8264 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 8265 * the lookat transformation will be applied first! 8266 * <p> 8267 * In order to set the matrix to a rotation transformation without post-multiplying it, 8268 * use {@link #rotationTowards(Vector3d, Vector3d) rotationTowards()}. 8269 * <p> 8270 * This method is equivalent to calling: <code>mul(new Matrix4x3d().lookAt(new Vector3d(), new Vector3d(dir).negate(), up).invert(), dest)</code> 8271 * 8272 * @see #rotateTowards(double, double, double, double, double, double, Matrix4x3d) 8273 * @see #rotationTowards(Vector3d, Vector3d) 8274 * 8275 * @param dir 8276 * the direction to rotate towards 8277 * @param up 8278 * the up vector 8279 * @param dest 8280 * will hold the result 8281 * @return dest 8282 */ 8283 public Matrix4x3d rotateTowards(ref Vector3d dir, Vector3d up, ref Matrix4x3d dest) { 8284 return rotateTowards(dir.x, dir.y, dir.z, up.x, up.y, up.z, dest); 8285 } 8286 8287 /** 8288 * Apply a model transformation to this matrix for a right-handed coordinate system, 8289 * that aligns the local <code>+Z</code> axis with <code>dir</code>. 8290 * <p> 8291 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 8292 * then the new matrix will be <code>M * L</code>. So when transforming a 8293 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 8294 * the lookat transformation will be applied first! 8295 * <p> 8296 * In order to set the matrix to a rotation transformation without post-multiplying it, 8297 * use {@link #rotationTowards(Vector3d, Vector3d) rotationTowards()}. 8298 * <p> 8299 * This method is equivalent to calling: <code>mul(new Matrix4x3d().lookAt(new Vector3d(), new Vector3d(dir).negate(), up).invert())</code> 8300 * 8301 * @see #rotateTowards(double, double, double, double, double, double) 8302 * @see #rotationTowards(Vector3d, Vector3d) 8303 * 8304 * @param dir 8305 * the direction to orient towards 8306 * @param up 8307 * the up vector 8308 * @return this 8309 */ 8310 ref public Matrix4x3d rotateTowards(ref Vector3d dir, Vector3d up) return { 8311 rotateTowards(dir.x, dir.y, dir.z, up.x, up.y, up.z, this); 8312 return this; 8313 } 8314 8315 /** 8316 * Apply a model transformation to this matrix for a right-handed coordinate system, 8317 * that aligns the local <code>+Z</code> axis with <code>(dirX, dirY, dirZ)</code>. 8318 * <p> 8319 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 8320 * then the new matrix will be <code>M * L</code>. So when transforming a 8321 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 8322 * the lookat transformation will be applied first! 8323 * <p> 8324 * In order to set the matrix to a rotation transformation without post-multiplying it, 8325 * use {@link #rotationTowards(double, double, double, double, double, double) rotationTowards()}. 8326 * <p> 8327 * This method is equivalent to calling: <code>mul(new Matrix4x3d().lookAt(0, 0, 0, -dirX, -dirY, -dirZ, upX, upY, upZ).invert())</code> 8328 * 8329 * @see #rotateTowards(Vector3d, Vector3d) 8330 * @see #rotationTowards(double, double, double, double, double, double) 8331 * 8332 * @param dirX 8333 * the x-coordinate of the direction to rotate towards 8334 * @param dirY 8335 * the y-coordinate of the direction to rotate towards 8336 * @param dirZ 8337 * the z-coordinate of the direction to rotate towards 8338 * @param upX 8339 * the x-coordinate of the up vector 8340 * @param upY 8341 * the y-coordinate of the up vector 8342 * @param upZ 8343 * the z-coordinate of the up vector 8344 * @return this 8345 */ 8346 ref public Matrix4x3d rotateTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ) return { 8347 rotateTowards(dirX, dirY, dirZ, upX, upY, upZ, this); 8348 return this; 8349 } 8350 8351 /** 8352 * Apply a model transformation to this matrix for a right-handed coordinate system, 8353 * that aligns the local <code>+Z</code> axis with <code>(dirX, dirY, dirZ)</code> 8354 * and store the result in <code>dest</code>. 8355 * <p> 8356 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 8357 * then the new matrix will be <code>M * L</code>. So when transforming a 8358 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 8359 * the lookat transformation will be applied first! 8360 * <p> 8361 * In order to set the matrix to a rotation transformation without post-multiplying it, 8362 * use {@link #rotationTowards(double, double, double, double, double, double) rotationTowards()}. 8363 * <p> 8364 * This method is equivalent to calling: <code>mul(new Matrix4x3d().lookAt(0, 0, 0, -dirX, -dirY, -dirZ, upX, upY, upZ).invert(), dest)</code> 8365 * 8366 * @see #rotateTowards(Vector3d, Vector3d) 8367 * @see #rotationTowards(double, double, double, double, double, double) 8368 * 8369 * @param dirX 8370 * the x-coordinate of the direction to rotate towards 8371 * @param dirY 8372 * the y-coordinate of the direction to rotate towards 8373 * @param dirZ 8374 * the z-coordinate of the direction to rotate towards 8375 * @param upX 8376 * the x-coordinate of the up vector 8377 * @param upY 8378 * the y-coordinate of the up vector 8379 * @param upZ 8380 * the z-coordinate of the up vector 8381 * @param dest 8382 * will hold the result 8383 * @return dest 8384 */ 8385 public Matrix4x3d rotateTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ, ref Matrix4x3d dest) { 8386 // Normalize direction 8387 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 8388 double ndirX = dirX * invDirLength; 8389 double ndirY = dirY * invDirLength; 8390 double ndirZ = dirZ * invDirLength; 8391 // left = up x direction 8392 double leftX, leftY, leftZ; 8393 leftX = upY * ndirZ - upZ * ndirY; 8394 leftY = upZ * ndirX - upX * ndirZ; 8395 leftZ = upX * ndirY - upY * ndirX; 8396 // normalize left 8397 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 8398 leftX *= invLeftLength; 8399 leftY *= invLeftLength; 8400 leftZ *= invLeftLength; 8401 // up = direction x left 8402 double upnX = ndirY * leftZ - ndirZ * leftY; 8403 double upnY = ndirZ * leftX - ndirX * leftZ; 8404 double upnZ = ndirX * leftY - ndirY * leftX; 8405 double rm00 = leftX; 8406 double rm01 = leftY; 8407 double rm02 = leftZ; 8408 double rm10 = upnX; 8409 double rm11 = upnY; 8410 double rm12 = upnZ; 8411 double rm20 = ndirX; 8412 double rm21 = ndirY; 8413 double rm22 = ndirZ; 8414 dest.m30 = m30; 8415 dest.m31 = m31; 8416 dest.m32 = m32; 8417 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 8418 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 8419 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 8420 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 8421 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 8422 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 8423 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 8424 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 8425 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 8426 dest.m00 = nm00; 8427 dest.m01 = nm01; 8428 dest.m02 = nm02; 8429 dest.m10 = nm10; 8430 dest.m11 = nm11; 8431 dest.m12 = nm12; 8432 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 8433 return dest; 8434 } 8435 8436 /** 8437 * Set this matrix to a model transformation for a right-handed coordinate system, 8438 * that aligns the local <code>-z</code> axis with <code>dir</code>. 8439 * <p> 8440 * In order to apply the rotation transformation to a previous existing transformation, 8441 * use {@link #rotateTowards(double, double, double, double, double, double) rotateTowards}. 8442 * <p> 8443 * This method is equivalent to calling: <code>setLookAt(new Vector3d(), new Vector3d(dir).negate(), up).invert()</code> 8444 * 8445 * @see #rotationTowards(Vector3d, Vector3d) 8446 * @see #rotateTowards(double, double, double, double, double, double) 8447 * 8448 * @param dir 8449 * the direction to orient the local -z axis towards 8450 * @param up 8451 * the up vector 8452 * @return this 8453 */ 8454 ref public Matrix4x3d rotationTowards(ref Vector3d dir, Vector3d up) return { 8455 return rotationTowards(dir.x, dir.y, dir.z, up.x, up.y, up.z); 8456 } 8457 8458 /** 8459 * Set this matrix to a model transformation for a right-handed coordinate system, 8460 * that aligns the local <code>-z</code> axis with <code>(dirX, dirY, dirZ)</code>. 8461 * <p> 8462 * In order to apply the rotation transformation to a previous existing transformation, 8463 * use {@link #rotateTowards(double, double, double, double, double, double) rotateTowards}. 8464 * <p> 8465 * This method is equivalent to calling: <code>setLookAt(0, 0, 0, -dirX, -dirY, -dirZ, upX, upY, upZ).invert()</code> 8466 * 8467 * @see #rotateTowards(Vector3d, Vector3d) 8468 * @see #rotationTowards(double, double, double, double, double, double) 8469 * 8470 * @param dirX 8471 * the x-coordinate of the direction to rotate towards 8472 * @param dirY 8473 * the y-coordinate of the direction to rotate towards 8474 * @param dirZ 8475 * the z-coordinate of the direction to rotate towards 8476 * @param upX 8477 * the x-coordinate of the up vector 8478 * @param upY 8479 * the y-coordinate of the up vector 8480 * @param upZ 8481 * the z-coordinate of the up vector 8482 * @return this 8483 */ 8484 ref public Matrix4x3d rotationTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ) return { 8485 // Normalize direction 8486 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 8487 double ndirX = dirX * invDirLength; 8488 double ndirY = dirY * invDirLength; 8489 double ndirZ = dirZ * invDirLength; 8490 // left = up x direction 8491 double leftX, leftY, leftZ; 8492 leftX = upY * ndirZ - upZ * ndirY; 8493 leftY = upZ * ndirX - upX * ndirZ; 8494 leftZ = upX * ndirY - upY * ndirX; 8495 // normalize left 8496 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 8497 leftX *= invLeftLength; 8498 leftY *= invLeftLength; 8499 leftZ *= invLeftLength; 8500 // up = direction x left 8501 double upnX = ndirY * leftZ - ndirZ * leftY; 8502 double upnY = ndirZ * leftX - ndirX * leftZ; 8503 double upnZ = ndirX * leftY - ndirY * leftX; 8504 this.m00 = leftX; 8505 this.m01 = leftY; 8506 this.m02 = leftZ; 8507 this.m10 = upnX; 8508 this.m11 = upnY; 8509 this.m12 = upnZ; 8510 this.m20 = ndirX; 8511 this.m21 = ndirY; 8512 this.m22 = ndirZ; 8513 this.m30 = 0.0; 8514 this.m31 = 0.0; 8515 this.m32 = 0.0; 8516 properties = PROPERTY_ORTHONORMAL; 8517 return this; 8518 } 8519 8520 /** 8521 * Set this matrix to a model transformation for a right-handed coordinate system, 8522 * that translates to the given <code>pos</code> and aligns the local <code>-z</code> 8523 * axis with <code>dir</code>. 8524 * <p> 8525 * This method is equivalent to calling: <code>translation(pos).rotateTowards(dir, up)</code> 8526 * 8527 * @see #translation(Vector3d) 8528 * @see #rotateTowards(Vector3d, Vector3d) 8529 * 8530 * @param pos 8531 * the position to translate to 8532 * @param dir 8533 * the direction to rotate towards 8534 * @param up 8535 * the up vector 8536 * @return this 8537 */ 8538 ref public Matrix4x3d translationRotateTowards(Vector3d pos, ref Vector3d dir, Vector3d up) return { 8539 return translationRotateTowards(pos.x, pos.y, pos.z, dir.x, dir.y, dir.z, up.x, up.y, up.z); 8540 } 8541 8542 /** 8543 * Set this matrix to a model transformation for a right-handed coordinate system, 8544 * that translates to the given <code>(posX, posY, posZ)</code> and aligns the local <code>-z</code> 8545 * axis with <code>(dirX, dirY, dirZ)</code>. 8546 * <p> 8547 * This method is equivalent to calling: <code>translation(posX, posY, posZ).rotateTowards(dirX, dirY, dirZ, upX, upY, upZ)</code> 8548 * 8549 * @see #translation(double, double, double) 8550 * @see #rotateTowards(double, double, double, double, double, double) 8551 * 8552 * @param posX 8553 * the x-coordinate of the position to translate to 8554 * @param posY 8555 * the y-coordinate of the position to translate to 8556 * @param posZ 8557 * the z-coordinate of the position to translate to 8558 * @param dirX 8559 * the x-coordinate of the direction to rotate towards 8560 * @param dirY 8561 * the y-coordinate of the direction to rotate towards 8562 * @param dirZ 8563 * the z-coordinate of the direction to rotate towards 8564 * @param upX 8565 * the x-coordinate of the up vector 8566 * @param upY 8567 * the y-coordinate of the up vector 8568 * @param upZ 8569 * the z-coordinate of the up vector 8570 * @return this 8571 */ 8572 ref public Matrix4x3d translationRotateTowards(double posX, double posY, double posZ, double dirX, double dirY, double dirZ, double upX, double upY, double upZ) return { 8573 // Normalize direction 8574 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 8575 double ndirX = dirX * invDirLength; 8576 double ndirY = dirY * invDirLength; 8577 double ndirZ = dirZ * invDirLength; 8578 // left = up x direction 8579 double leftX, leftY, leftZ; 8580 leftX = upY * ndirZ - upZ * ndirY; 8581 leftY = upZ * ndirX - upX * ndirZ; 8582 leftZ = upX * ndirY - upY * ndirX; 8583 // normalize left 8584 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 8585 leftX *= invLeftLength; 8586 leftY *= invLeftLength; 8587 leftZ *= invLeftLength; 8588 // up = direction x left 8589 double upnX = ndirY * leftZ - ndirZ * leftY; 8590 double upnY = ndirZ * leftX - ndirX * leftZ; 8591 double upnZ = ndirX * leftY - ndirY * leftX; 8592 this.m00 = leftX; 8593 this.m01 = leftY; 8594 this.m02 = leftZ; 8595 this.m10 = upnX; 8596 this.m11 = upnY; 8597 this.m12 = upnZ; 8598 this.m20 = ndirX; 8599 this.m21 = ndirY; 8600 this.m22 = ndirZ; 8601 this.m30 = posX; 8602 this.m31 = posY; 8603 this.m32 = posZ; 8604 properties = PROPERTY_ORTHONORMAL; 8605 return this; 8606 } 8607 8608 public Vector3d getEulerAnglesZYX(ref Vector3d dest) { 8609 dest.x = Math.atan2(m12, m22); 8610 dest.y = Math.atan2(-m02, Math.sqrt(1.0 - m02 * m02)); 8611 dest.z = Math.atan2(m01, m00); 8612 return dest; 8613 } 8614 8615 public Vector3d getEulerAnglesXYZ(ref Vector3d dest) { 8616 dest.x = Math.atan2(-m21, m22); 8617 dest.y = Math.atan2(m20, Math.sqrt(1.0 - m20 * m20)); 8618 dest.z = Math.atan2(-m10, m00); 8619 return dest; 8620 } 8621 8622 /** 8623 * Apply an oblique projection transformation to this matrix with the given values for <code>a</code> and 8624 * <code>b</code>. 8625 * <p> 8626 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the oblique transformation matrix, 8627 * then the new matrix will be <code>M * O</code>. So when transforming a 8628 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 8629 * oblique transformation will be applied first! 8630 * <p> 8631 * The oblique transformation is defined as: 8632 * <pre> 8633 * x' = x + a*z 8634 * y' = y + a*z 8635 * z' = z 8636 * </pre> 8637 * or in matrix form: 8638 * <pre> 8639 * 1 0 a 0 8640 * 0 1 b 0 8641 * 0 0 1 0 8642 * </pre> 8643 * 8644 * @param a 8645 * the value for the z factor that applies to x 8646 * @param b 8647 * the value for the z factor that applies to y 8648 * @return this 8649 */ 8650 ref public Matrix4x3d obliqueZ(double a, double b) return { 8651 this.m20 = m00 * a + m10 * b + m20; 8652 this.m21 = m01 * a + m11 * b + m21; 8653 this.m22 = m02 * a + m12 * b + m22; 8654 this.properties = 0; 8655 return this; 8656 } 8657 8658 /** 8659 * Apply an oblique projection transformation to this matrix with the given values for <code>a</code> and 8660 * <code>b</code> and store the result in <code>dest</code>. 8661 * <p> 8662 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the oblique transformation matrix, 8663 * then the new matrix will be <code>M * O</code>. So when transforming a 8664 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 8665 * oblique transformation will be applied first! 8666 * <p> 8667 * The oblique transformation is defined as: 8668 * <pre> 8669 * x' = x + a*z 8670 * y' = y + a*z 8671 * z' = z 8672 * </pre> 8673 * or in matrix form: 8674 * <pre> 8675 * 1 0 a 0 8676 * 0 1 b 0 8677 * 0 0 1 0 8678 * </pre> 8679 * 8680 * @param a 8681 * the value for the z factor that applies to x 8682 * @param b 8683 * the value for the z factor that applies to y 8684 * @param dest 8685 * will hold the result 8686 * @return dest 8687 */ 8688 public Matrix4x3d obliqueZ(double a, double b, ref Matrix4x3d dest) { 8689 dest.m00 = m00; 8690 dest.m01 = m01; 8691 dest.m02 = m02; 8692 dest.m10 = m10; 8693 dest.m11 = m11; 8694 dest.m12 = m12; 8695 dest.m20 = m00 * a + m10 * b + m20; 8696 dest.m21 = m01 * a + m11 * b + m21; 8697 dest.m22 = m02 * a + m12 * b + m22; 8698 dest.m30 = m30; 8699 dest.m31 = m31; 8700 dest.m32 = m32; 8701 dest.properties = 0; 8702 return dest; 8703 } 8704 8705 /** 8706 * Multiply <code>this</code> by the matrix 8707 * <pre> 8708 * 1 0 0 0 8709 * 0 0 1 0 8710 * 0 1 0 0 8711 * </pre> 8712 * 8713 * @return this 8714 */ 8715 ref public Matrix4x3d mapXZY() return { 8716 mapXZY(this); 8717 return this; 8718 } 8719 public Matrix4x3d mapXZY(ref Matrix4x3d dest) { 8720 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 8721 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); 8722 } 8723 /** 8724 * Multiply <code>this</code> by the matrix 8725 * <pre> 8726 * 1 0 0 0 8727 * 0 0 -1 0 8728 * 0 1 0 0 8729 * </pre> 8730 * 8731 * @return this 8732 */ 8733 ref public Matrix4x3d mapXZnY() return { 8734 mapXZnY(this); 8735 return this; 8736 } 8737 public Matrix4x3d mapXZnY(ref Matrix4x3d dest) { 8738 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 8739 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); 8740 } 8741 /** 8742 * Multiply <code>this</code> by the matrix 8743 * <pre> 8744 * 1 0 0 0 8745 * 0 -1 0 0 8746 * 0 0 -1 0 8747 * </pre> 8748 * 8749 * @return this 8750 */ 8751 ref public Matrix4x3d mapXnYnZ() return { 8752 mapXnYnZ(this); 8753 return this; 8754 } 8755 public Matrix4x3d mapXnYnZ(ref Matrix4x3d dest) { 8756 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); 8757 } 8758 /** 8759 * Multiply <code>this</code> by the matrix 8760 * <pre> 8761 * 1 0 0 0 8762 * 0 0 1 0 8763 * 0 -1 0 0 8764 * </pre> 8765 * 8766 * @return this 8767 */ 8768 ref public Matrix4x3d mapXnZY() return { 8769 mapXnZY(this); 8770 return this; 8771 } 8772 public Matrix4x3d mapXnZY(ref Matrix4x3d dest) { 8773 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 8774 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); 8775 } 8776 /** 8777 * Multiply <code>this</code> by the matrix 8778 * <pre> 8779 * 1 0 0 0 8780 * 0 0 -1 0 8781 * 0 -1 0 0 8782 * </pre> 8783 * 8784 * @return this 8785 */ 8786 ref public Matrix4x3d mapXnZnY() return { 8787 mapXnZnY(this); 8788 return this; 8789 } 8790 public Matrix4x3d mapXnZnY(ref Matrix4x3d dest) { 8791 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 8792 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); 8793 } 8794 /** 8795 * Multiply <code>this</code> by the matrix 8796 * <pre> 8797 * 0 1 0 0 8798 * 1 0 0 0 8799 * 0 0 1 0 8800 * </pre> 8801 * 8802 * @return this 8803 */ 8804 ref public Matrix4x3d mapYXZ() return { 8805 mapYXZ(this); 8806 return this; 8807 } 8808 public Matrix4x3d mapYXZ(ref Matrix4x3d dest) { 8809 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8810 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); 8811 } 8812 /** 8813 * Multiply <code>this</code> by the matrix 8814 * <pre> 8815 * 0 1 0 0 8816 * 1 0 0 0 8817 * 0 0 -1 0 8818 * </pre> 8819 * 8820 * @return this 8821 */ 8822 ref public Matrix4x3d mapYXnZ() return { 8823 mapYXnZ(this); 8824 return this; 8825 } 8826 public Matrix4x3d mapYXnZ(ref Matrix4x3d dest) { 8827 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8828 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); 8829 } 8830 /** 8831 * Multiply <code>this</code> by the matrix 8832 * <pre> 8833 * 0 0 1 0 8834 * 1 0 0 0 8835 * 0 1 0 0 8836 * </pre> 8837 * 8838 * @return this 8839 */ 8840 ref public Matrix4x3d mapYZX() return { 8841 mapYZX(this); 8842 return this; 8843 } 8844 public Matrix4x3d mapYZX(ref Matrix4x3d dest) { 8845 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8846 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); 8847 } 8848 /** 8849 * Multiply <code>this</code> by the matrix 8850 * <pre> 8851 * 0 0 -1 0 8852 * 1 0 0 0 8853 * 0 1 0 0 8854 * </pre> 8855 * 8856 * @return this 8857 */ 8858 ref public Matrix4x3d mapYZnX() return { 8859 mapYZnX(this); 8860 return this; 8861 } 8862 public Matrix4x3d mapYZnX(ref Matrix4x3d dest) { 8863 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8864 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); 8865 } 8866 /** 8867 * Multiply <code>this</code> by the matrix 8868 * <pre> 8869 * 0 -1 0 0 8870 * 1 0 0 0 8871 * 0 0 1 0 8872 * </pre> 8873 * 8874 * @return this 8875 */ 8876 ref public Matrix4x3d mapYnXZ() return { 8877 mapYnXZ(this); 8878 return this; 8879 } 8880 public Matrix4x3d mapYnXZ(ref Matrix4x3d dest) { 8881 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8882 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); 8883 } 8884 /** 8885 * Multiply <code>this</code> by the matrix 8886 * <pre> 8887 * 0 -1 0 0 8888 * 1 0 0 0 8889 * 0 0 -1 0 8890 * </pre> 8891 * 8892 * @return this 8893 */ 8894 ref public Matrix4x3d mapYnXnZ() return { 8895 mapYnXnZ(this); 8896 return this; 8897 } 8898 public Matrix4x3d mapYnXnZ(ref Matrix4x3d dest) { 8899 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8900 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); 8901 } 8902 /** 8903 * Multiply <code>this</code> by the matrix 8904 * <pre> 8905 * 0 0 1 0 8906 * 1 0 0 0 8907 * 0 -1 0 0 8908 * </pre> 8909 * 8910 * @return this 8911 */ 8912 ref public Matrix4x3d mapYnZX() return { 8913 mapYnZX(this); 8914 return this; 8915 } 8916 public Matrix4x3d mapYnZX(ref Matrix4x3d dest) { 8917 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8918 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); 8919 } 8920 /** 8921 * Multiply <code>this</code> by the matrix 8922 * <pre> 8923 * 0 0 -1 0 8924 * 1 0 0 0 8925 * 0 -1 0 0 8926 * </pre> 8927 * 8928 * @return this 8929 */ 8930 ref public Matrix4x3d mapYnZnX() return { 8931 mapYnZnX(this); 8932 return this; 8933 } 8934 public Matrix4x3d mapYnZnX(ref Matrix4x3d dest) { 8935 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8936 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); 8937 } 8938 /** 8939 * Multiply <code>this</code> by the matrix 8940 * <pre> 8941 * 0 1 0 0 8942 * 0 0 1 0 8943 * 1 0 0 0 8944 * </pre> 8945 * 8946 * @return this 8947 */ 8948 ref public Matrix4x3d mapZXY() return { 8949 mapZXY(this); 8950 return this; 8951 } 8952 public Matrix4x3d mapZXY(ref Matrix4x3d dest) { 8953 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8954 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 8955 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); 8956 } 8957 /** 8958 * Multiply <code>this</code> by the matrix 8959 * <pre> 8960 * 0 1 0 0 8961 * 0 0 -1 0 8962 * 1 0 0 0 8963 * </pre> 8964 * 8965 * @return this 8966 */ 8967 ref public Matrix4x3d mapZXnY() return { 8968 mapZXnY(this); 8969 return this; 8970 } 8971 public Matrix4x3d mapZXnY(ref Matrix4x3d dest) { 8972 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8973 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 8974 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); 8975 } 8976 /** 8977 * Multiply <code>this</code> by the matrix 8978 * <pre> 8979 * 0 0 1 0 8980 * 0 1 0 0 8981 * 1 0 0 0 8982 * </pre> 8983 * 8984 * @return this 8985 */ 8986 ref public Matrix4x3d mapZYX() return { 8987 mapZYX(this); 8988 return this; 8989 } 8990 public Matrix4x3d mapZYX(ref Matrix4x3d dest) { 8991 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8992 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); 8993 } 8994 /** 8995 * Multiply <code>this</code> by the matrix 8996 * <pre> 8997 * 0 0 -1 0 8998 * 0 1 0 0 8999 * 1 0 0 0 9000 * </pre> 9001 * 9002 * @return this 9003 */ 9004 ref public Matrix4x3d mapZYnX() return { 9005 mapZYnX(this); 9006 return this; 9007 } 9008 public Matrix4x3d mapZYnX(ref Matrix4x3d dest) { 9009 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9010 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); 9011 } 9012 /** 9013 * Multiply <code>this</code> by the matrix 9014 * <pre> 9015 * 0 -1 0 0 9016 * 0 0 1 0 9017 * 1 0 0 0 9018 * </pre> 9019 * 9020 * @return this 9021 */ 9022 ref public Matrix4x3d mapZnXY() return { 9023 mapZnXY(this); 9024 return this; 9025 } 9026 public Matrix4x3d mapZnXY(ref Matrix4x3d dest) { 9027 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9028 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9029 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); 9030 } 9031 /** 9032 * Multiply <code>this</code> by the matrix 9033 * <pre> 9034 * 0 -1 0 0 9035 * 0 0 -1 0 9036 * 1 0 0 0 9037 * </pre> 9038 * 9039 * @return this 9040 */ 9041 ref public Matrix4x3d mapZnXnY() return { 9042 mapZnXnY(this); 9043 return this; 9044 } 9045 public Matrix4x3d mapZnXnY(ref Matrix4x3d dest) { 9046 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9047 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9048 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); 9049 } 9050 /** 9051 * Multiply <code>this</code> by the matrix 9052 * <pre> 9053 * 0 0 1 0 9054 * 0 -1 0 0 9055 * 1 0 0 0 9056 * </pre> 9057 * 9058 * @return this 9059 */ 9060 ref public Matrix4x3d mapZnYX() return { 9061 mapZnYX(this); 9062 return this; 9063 } 9064 public Matrix4x3d mapZnYX(ref Matrix4x3d dest) { 9065 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9066 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); 9067 } 9068 /** 9069 * Multiply <code>this</code> by the matrix 9070 * <pre> 9071 * 0 0 -1 0 9072 * 0 -1 0 0 9073 * 1 0 0 0 9074 * </pre> 9075 * 9076 * @return this 9077 */ 9078 ref public Matrix4x3d mapZnYnX() return { 9079 mapZnYnX(this); 9080 return this; 9081 } 9082 public Matrix4x3d mapZnYnX(ref Matrix4x3d dest) { 9083 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9084 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); 9085 } 9086 /** 9087 * Multiply <code>this</code> by the matrix 9088 * <pre> 9089 * -1 0 0 0 9090 * 0 1 0 0 9091 * 0 0 -1 0 9092 * </pre> 9093 * 9094 * @return this 9095 */ 9096 ref public Matrix4x3d mapnXYnZ() return { 9097 mapnXYnZ(this); 9098 return this; 9099 } 9100 public Matrix4x3d mapnXYnZ(ref Matrix4x3d dest) { 9101 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); 9102 } 9103 /** 9104 * Multiply <code>this</code> by the matrix 9105 * <pre> 9106 * -1 0 0 0 9107 * 0 0 1 0 9108 * 0 1 0 0 9109 * </pre> 9110 * 9111 * @return this 9112 */ 9113 ref public Matrix4x3d mapnXZY() return { 9114 mapnXZY(this); 9115 return this; 9116 } 9117 public Matrix4x3d mapnXZY(ref Matrix4x3d dest) { 9118 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9119 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); 9120 } 9121 /** 9122 * Multiply <code>this</code> by the matrix 9123 * <pre> 9124 * -1 0 0 0 9125 * 0 0 -1 0 9126 * 0 1 0 0 9127 * </pre> 9128 * 9129 * @return this 9130 */ 9131 ref public Matrix4x3d mapnXZnY() return { 9132 mapnXZnY(this); 9133 return this; 9134 } 9135 public Matrix4x3d mapnXZnY(ref Matrix4x3d dest) { 9136 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9137 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); 9138 } 9139 /** 9140 * Multiply <code>this</code> by the matrix 9141 * <pre> 9142 * -1 0 0 0 9143 * 0 -1 0 0 9144 * 0 0 1 0 9145 * </pre> 9146 * 9147 * @return this 9148 */ 9149 ref public Matrix4x3d mapnXnYZ() return { 9150 mapnXnYZ(this); 9151 return this; 9152 } 9153 public Matrix4x3d mapnXnYZ(ref Matrix4x3d dest) { 9154 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); 9155 } 9156 /** 9157 * Multiply <code>this</code> by the matrix 9158 * <pre> 9159 * -1 0 0 0 9160 * 0 -1 0 0 9161 * 0 0 -1 0 9162 * </pre> 9163 * 9164 * @return this 9165 */ 9166 ref public Matrix4x3d mapnXnYnZ() return { 9167 mapnXnYnZ(this); 9168 return this; 9169 } 9170 public Matrix4x3d mapnXnYnZ(ref Matrix4x3d dest) { 9171 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); 9172 } 9173 /** 9174 * Multiply <code>this</code> by the matrix 9175 * <pre> 9176 * -1 0 0 0 9177 * 0 0 1 0 9178 * 0 -1 0 0 9179 * </pre> 9180 * 9181 * @return this 9182 */ 9183 ref public Matrix4x3d mapnXnZY() return { 9184 mapnXnZY(this); 9185 return this; 9186 } 9187 public Matrix4x3d mapnXnZY(ref Matrix4x3d dest) { 9188 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9189 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); 9190 } 9191 /** 9192 * Multiply <code>this</code> by the matrix 9193 * <pre> 9194 * -1 0 0 0 9195 * 0 0 -1 0 9196 * 0 -1 0 0 9197 * </pre> 9198 * 9199 * @return this 9200 */ 9201 ref public Matrix4x3d mapnXnZnY() return { 9202 mapnXnZnY(this); 9203 return this; 9204 } 9205 public Matrix4x3d mapnXnZnY(ref Matrix4x3d dest) { 9206 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9207 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); 9208 } 9209 /** 9210 * Multiply <code>this</code> by the matrix 9211 * <pre> 9212 * 0 1 0 0 9213 * -1 0 0 0 9214 * 0 0 1 0 9215 * </pre> 9216 * 9217 * @return this 9218 */ 9219 ref public Matrix4x3d mapnYXZ() return { 9220 mapnYXZ(this); 9221 return this; 9222 } 9223 public Matrix4x3d mapnYXZ(ref Matrix4x3d dest) { 9224 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9225 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); 9226 } 9227 /** 9228 * Multiply <code>this</code> by the matrix 9229 * <pre> 9230 * 0 1 0 0 9231 * -1 0 0 0 9232 * 0 0 -1 0 9233 * </pre> 9234 * 9235 * @return this 9236 */ 9237 ref public Matrix4x3d mapnYXnZ() return { 9238 mapnYXnZ(this); 9239 return this; 9240 } 9241 public Matrix4x3d mapnYXnZ(ref Matrix4x3d dest) { 9242 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9243 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); 9244 } 9245 /** 9246 * Multiply <code>this</code> by the matrix 9247 * <pre> 9248 * 0 0 1 0 9249 * -1 0 0 0 9250 * 0 1 0 0 9251 * </pre> 9252 * 9253 * @return this 9254 */ 9255 ref public Matrix4x3d mapnYZX() return { 9256 mapnYZX(this); 9257 return this; 9258 } 9259 public Matrix4x3d mapnYZX(ref Matrix4x3d dest) { 9260 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9261 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); 9262 } 9263 /** 9264 * Multiply <code>this</code> by the matrix 9265 * <pre> 9266 * 0 0 -1 0 9267 * -1 0 0 0 9268 * 0 1 0 0 9269 * </pre> 9270 * 9271 * @return this 9272 */ 9273 ref public Matrix4x3d mapnYZnX() return { 9274 mapnYZnX(this); 9275 return this; 9276 } 9277 public Matrix4x3d mapnYZnX(ref Matrix4x3d dest) { 9278 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9279 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); 9280 } 9281 /** 9282 * Multiply <code>this</code> by the matrix 9283 * <pre> 9284 * 0 -1 0 0 9285 * -1 0 0 0 9286 * 0 0 1 0 9287 * </pre> 9288 * 9289 * @return this 9290 */ 9291 ref public Matrix4x3d mapnYnXZ() return { 9292 mapnYnXZ(this); 9293 return this; 9294 } 9295 public Matrix4x3d mapnYnXZ(ref Matrix4x3d dest) { 9296 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9297 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); 9298 } 9299 /** 9300 * Multiply <code>this</code> by the matrix 9301 * <pre> 9302 * 0 -1 0 0 9303 * -1 0 0 0 9304 * 0 0 -1 0 9305 * </pre> 9306 * 9307 * @return this 9308 */ 9309 ref public Matrix4x3d mapnYnXnZ() return { 9310 mapnYnXnZ(this); 9311 return this; 9312 } 9313 public Matrix4x3d mapnYnXnZ(ref Matrix4x3d dest) { 9314 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9315 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); 9316 } 9317 /** 9318 * Multiply <code>this</code> by the matrix 9319 * <pre> 9320 * 0 0 1 0 9321 * -1 0 0 0 9322 * 0 -1 0 0 9323 * </pre> 9324 * 9325 * @return this 9326 */ 9327 ref public Matrix4x3d mapnYnZX() return { 9328 mapnYnZX(this); 9329 return this; 9330 } 9331 public Matrix4x3d mapnYnZX(ref Matrix4x3d dest) { 9332 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9333 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); 9334 } 9335 /** 9336 * Multiply <code>this</code> by the matrix 9337 * <pre> 9338 * 0 0 -1 0 9339 * -1 0 0 0 9340 * 0 -1 0 0 9341 * </pre> 9342 * 9343 * @return this 9344 */ 9345 ref public Matrix4x3d mapnYnZnX() return { 9346 mapnYnZnX(this); 9347 return this; 9348 } 9349 public Matrix4x3d mapnYnZnX(ref Matrix4x3d dest) { 9350 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9351 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); 9352 } 9353 /** 9354 * Multiply <code>this</code> by the matrix 9355 * <pre> 9356 * 0 1 0 0 9357 * 0 0 1 0 9358 * -1 0 0 0 9359 * </pre> 9360 * 9361 * @return this 9362 */ 9363 ref public Matrix4x3d mapnZXY() return { 9364 mapnZXY(this); 9365 return this; 9366 } 9367 public Matrix4x3d mapnZXY(ref Matrix4x3d dest) { 9368 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9369 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9370 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); 9371 } 9372 /** 9373 * Multiply <code>this</code> by the matrix 9374 * <pre> 9375 * 0 1 0 0 9376 * 0 0 -1 0 9377 * -1 0 0 0 9378 * </pre> 9379 * 9380 * @return this 9381 */ 9382 ref public Matrix4x3d mapnZXnY() return { 9383 mapnZXnY(this); 9384 return this; 9385 } 9386 public Matrix4x3d mapnZXnY(ref Matrix4x3d dest) { 9387 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9388 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9389 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); 9390 } 9391 /** 9392 * Multiply <code>this</code> by the matrix 9393 * <pre> 9394 * 0 0 1 0 9395 * 0 1 0 0 9396 * -1 0 0 0 9397 * </pre> 9398 * 9399 * @return this 9400 */ 9401 ref public Matrix4x3d mapnZYX() return { 9402 mapnZYX(this); 9403 return this; 9404 } 9405 public Matrix4x3d mapnZYX(ref Matrix4x3d dest) { 9406 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9407 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); 9408 } 9409 /** 9410 * Multiply <code>this</code> by the matrix 9411 * <pre> 9412 * 0 0 -1 0 9413 * 0 1 0 0 9414 * -1 0 0 0 9415 * </pre> 9416 * 9417 * @return this 9418 */ 9419 ref public Matrix4x3d mapnZYnX() return { 9420 mapnZYnX(this); 9421 return this; 9422 } 9423 public Matrix4x3d mapnZYnX(ref Matrix4x3d dest) { 9424 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9425 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); 9426 } 9427 /** 9428 * Multiply <code>this</code> by the matrix 9429 * <pre> 9430 * 0 -1 0 0 9431 * 0 0 1 0 9432 * -1 0 0 0 9433 * </pre> 9434 * 9435 * @return this 9436 */ 9437 ref public Matrix4x3d mapnZnXY() return { 9438 mapnZnXY(this); 9439 return this; 9440 } 9441 public Matrix4x3d mapnZnXY(ref Matrix4x3d dest) { 9442 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9443 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9444 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); 9445 } 9446 /** 9447 * Multiply <code>this</code> by the matrix 9448 * <pre> 9449 * 0 -1 0 0 9450 * 0 0 -1 0 9451 * -1 0 0 0 9452 * </pre> 9453 * 9454 * @return this 9455 */ 9456 ref public Matrix4x3d mapnZnXnY() return { 9457 mapnZnXnY(this); 9458 return this; 9459 } 9460 public Matrix4x3d mapnZnXnY(ref Matrix4x3d dest) { 9461 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9462 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9463 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); 9464 } 9465 /** 9466 * Multiply <code>this</code> by the matrix 9467 * <pre> 9468 * 0 0 1 0 9469 * 0 -1 0 0 9470 * -1 0 0 0 9471 * </pre> 9472 * 9473 * @return this 9474 */ 9475 ref public Matrix4x3d mapnZnYX() return { 9476 mapnZnYX(this); 9477 return this; 9478 } 9479 public Matrix4x3d mapnZnYX(ref Matrix4x3d dest) { 9480 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9481 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); 9482 } 9483 /** 9484 * Multiply <code>this</code> by the matrix 9485 * <pre> 9486 * 0 0 -1 0 9487 * 0 -1 0 0 9488 * -1 0 0 0 9489 * </pre> 9490 * 9491 * @return this 9492 */ 9493 ref public Matrix4x3d mapnZnYnX() return { 9494 mapnZnYnX(this); 9495 return this; 9496 } 9497 public Matrix4x3d mapnZnYnX(ref Matrix4x3d dest) { 9498 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9499 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); 9500 } 9501 9502 /** 9503 * Multiply <code>this</code> by the matrix 9504 * <pre> 9505 * -1 0 0 0 9506 * 0 1 0 0 9507 * 0 0 1 0 9508 * </pre> 9509 * 9510 * @return this 9511 */ 9512 ref public Matrix4x3d negateX() return { 9513 return _m00(-m00)._m01(-m01)._m02(-m02)._properties(properties & PROPERTY_ORTHONORMAL); 9514 } 9515 public Matrix4x3d negateX(ref Matrix4x3d dest) { 9516 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); 9517 } 9518 9519 /** 9520 * Multiply <code>this</code> by the matrix 9521 * <pre> 9522 * 1 0 0 0 9523 * 0 -1 0 0 9524 * 0 0 1 0 9525 * </pre> 9526 * 9527 * @return this 9528 */ 9529 ref public Matrix4x3d negateY() return { 9530 return _m10(-m10)._m11(-m11)._m12(-m12)._properties(properties & PROPERTY_ORTHONORMAL); 9531 } 9532 public Matrix4x3d negateY(ref Matrix4x3d dest) { 9533 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); 9534 } 9535 9536 /** 9537 * Multiply <code>this</code> by the matrix 9538 * <pre> 9539 * 1 0 0 0 9540 * 0 1 0 0 9541 * 0 0 -1 0 9542 * </pre> 9543 * 9544 * @return this 9545 */ 9546 ref public Matrix4x3d negateZ() return { 9547 return _m20(-m20)._m21(-m21)._m22(-m22)._properties(properties & PROPERTY_ORTHONORMAL); 9548 } 9549 public Matrix4x3d negateZ(ref Matrix4x3d dest) { 9550 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); 9551 } 9552 9553 public bool isFinite() { 9554 return Math.isFinite(m00) && Math.isFinite(m01) && Math.isFinite(m02) && 9555 Math.isFinite(m10) && Math.isFinite(m11) && Math.isFinite(m12) && 9556 Math.isFinite(m20) && Math.isFinite(m21) && Math.isFinite(m22) && 9557 Math.isFinite(m30) && Math.isFinite(m31) && Math.isFinite(m32); 9558 } 9559 }