1 /** 2 * Contains the definition of a 3x3 matrix 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<br> 6 * m01 m11 m21<br> 7 * m02 m12 m22<br> 8 * 9 * @author Richard Greenlees 10 * @author Kai Burjack 11 */ 12 module doml.matrix_3d; 13 14 import Math = doml.math; 15 import MemUtil = doml.mem_util; 16 17 import doml.matrix_2d; 18 import doml.matrix_4d; 19 import doml.matrix_4x3d; 20 21 import doml.vector_3d; 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 /** 53 * Contains the definition of a 3x3 matrix of doubles, and associated functions to transform 54 * it. The matrix is column-major to match OpenGL's interpretation, and it looks like this: 55 * <p> 56 * m00 m10 m20<br> 57 * m01 m11 m21<br> 58 * m02 m12 m22<br> 59 * 60 * @author Richard Greenlees 61 * @author Kai Burjack 62 */ 63 struct Matrix3d { 64 65 double m00 = 1.0; 66 double m01 = 0.0; 67 double m02 = 0.0; 68 69 double m10 = 0.0; 70 double m11 = 1.0; 71 double m12 = 0.0; 72 73 double m20 = 0.0; 74 double m21 = 0.0; 75 double m22 = 1.0; 76 77 /** 78 * Create a new {@link Matrix3d} by setting its uppper left 2x2 submatrix to the values of the given {@link Matrix2d} 79 * and the rest to identity. 80 * 81 * @param mat 82 * the {@link Matrix2d} 83 */ 84 this(Matrix2d mat) { 85 set(mat); 86 } 87 88 89 /** 90 * Create a new {@link Matrix3d} and initialize it with the values from the given matrix. 91 * 92 * @param mat 93 * the matrix to initialize this matrix with 94 */ 95 this(Matrix3d mat) { 96 set(mat); 97 } 98 99 100 /** 101 * Create a new {@link Matrix3d} and make it a copy of the upper left 3x3 of the given {@link Matrix4d}. 102 * 103 * @param mat 104 * the {@link Matrix4d} to copy the values from 105 */ 106 this(Matrix4d mat) { 107 set(mat); 108 } 109 110 /** 111 * Create a new {@link Matrix3d} and initialize its elements with the given values. 112 * 113 * @param m00 114 * the value of m00 115 * @param m01 116 * the value of m01 117 * @param m02 118 * the value of m02 119 * @param m10 120 * the value of m10 121 * @param m11 122 * the value of m11 123 * @param m12 124 * the value of m12 125 * @param m20 126 * the value of m20 127 * @param m21 128 * the value of m21 129 * @param m22 130 * the value of m22 131 */ 132 this(double m00, double m01, double m02, 133 double m10, double m11, double m12, 134 double m20, double m21, double m22) { 135 this.m00 = m00; 136 this.m01 = m01; 137 this.m02 = m02; 138 this.m10 = m10; 139 this.m11 = m11; 140 this.m12 = m12; 141 this.m20 = m20; 142 this.m21 = m21; 143 this.m22 = m22; 144 } 145 146 147 /** 148 * Create a new {@link Matrix3d} and initialize its three columns using the supplied vectors. 149 * 150 * @param col0 151 * the first column 152 * @param col1 153 * the second column 154 * @param col2 155 * the third column 156 */ 157 this(Vector3d col0, Vector3d col1, Vector3d col2) { 158 set(col0, col1, col2); 159 } 160 161 /** 162 * Set the value of the matrix element at column 0 and row 0. 163 * 164 * @param m00 165 * the new value 166 * @return this 167 */ 168 ref public Matrix3d setm00(double m00) return { 169 this.m00 = m00; 170 return this; 171 } 172 /** 173 * Set the value of the matrix element at column 0 and row 1. 174 * 175 * @param m01 176 * the new value 177 * @return this 178 */ 179 ref public Matrix3d setm01(double m01) return { 180 this.m01 = m01; 181 return this; 182 } 183 /** 184 * Set the value of the matrix element at column 0 and row 2. 185 * 186 * @param m02 187 * the new value 188 * @return this 189 */ 190 ref public Matrix3d setm02(double m02) return { 191 this.m02 = m02; 192 return this; 193 } 194 /** 195 * Set the value of the matrix element at column 1 and row 0. 196 * 197 * @param m10 198 * the new value 199 * @return this 200 */ 201 ref public Matrix3d setm10(double m10) return { 202 this.m10 = m10; 203 return this; 204 } 205 /** 206 * Set the value of the matrix element at column 1 and row 1. 207 * 208 * @param m11 209 * the new value 210 * @return this 211 */ 212 ref public Matrix3d setm11(double m11) return { 213 this.m11 = m11; 214 return this; 215 } 216 /** 217 * Set the value of the matrix element at column 1 and row 2. 218 * 219 * @param m12 220 * the new value 221 * @return this 222 */ 223 ref public Matrix3d setm12(double m12) return { 224 this.m12 = m12; 225 return this; 226 } 227 /** 228 * Set the value of the matrix element at column 2 and row 0. 229 * 230 * @param m20 231 * the new value 232 * @return this 233 */ 234 ref public Matrix3d setm20(double m20) return { 235 this.m20 = m20; 236 return this; 237 } 238 /** 239 * Set the value of the matrix element at column 2 and row 1. 240 * 241 * @param m21 242 * the new value 243 * @return this 244 */ 245 ref public Matrix3d setm21(double m21) return { 246 this.m21 = m21; 247 return this; 248 } 249 /** 250 * Set the value of the matrix element at column 2 and row 2. 251 * 252 * @param m22 253 * the new value 254 * @return this 255 */ 256 ref public Matrix3d setm22(double m22) return { 257 this.m22 = m22; 258 return this; 259 } 260 261 /** 262 * Set the value of the matrix element at column 0 and row 0. 263 * 264 * @param m00 265 * the new value 266 * @return this 267 */ 268 ref Matrix3d _m00(double m00) return { 269 this.m00 = m00; 270 return this; 271 } 272 /** 273 * Set the value of the matrix element at column 0 and row 1. 274 * 275 * @param m01 276 * the new value 277 * @return this 278 */ 279 ref Matrix3d _m01(double m01) return { 280 this.m01 = m01; 281 return this; 282 } 283 /** 284 * Set the value of the matrix element at column 0 and row 2. 285 * 286 * @param m02 287 * the new value 288 * @return this 289 */ 290 ref Matrix3d _m02(double m02) return { 291 this.m02 = m02; 292 return this; 293 } 294 /** 295 * Set the value of the matrix element at column 1 and row 0. 296 * 297 * @param m10 298 * the new value 299 * @return this 300 */ 301 ref Matrix3d _m10(double m10) return { 302 this.m10 = m10; 303 return this; 304 } 305 /** 306 * Set the value of the matrix element at column 1 and row 1. 307 * 308 * @param m11 309 * the new value 310 * @return this 311 */ 312 ref Matrix3d _m11(double m11) return { 313 this.m11 = m11; 314 return this; 315 } 316 /** 317 * Set the value of the matrix element at column 1 and row 2. 318 * 319 * @param m12 320 * the new value 321 * @return this 322 */ 323 ref Matrix3d _m12(double m12) return { 324 this.m12 = m12; 325 return this; 326 } 327 /** 328 * Set the value of the matrix element at column 2 and row 0. 329 * 330 * @param m20 331 * the new value 332 * @return this 333 */ 334 ref Matrix3d _m20(double m20) return { 335 this.m20 = m20; 336 return this; 337 } 338 /** 339 * Set the value of the matrix element at column 2 and row 1. 340 * 341 * @param m21 342 * the new value 343 * @return this 344 */ 345 ref Matrix3d _m21(double m21) return { 346 this.m21 = m21; 347 return this; 348 } 349 /** 350 * Set the value of the matrix element at column 2 and row 2. 351 * 352 * @param m22 353 * the new value 354 * @return this 355 */ 356 ref Matrix3d _m22(double m22) return { 357 this.m22 = m22; 358 return this; 359 } 360 361 /** 362 * Set the values in this matrix to the ones in m. 363 * 364 * @param m 365 * the matrix whose values will be copied 366 * @return this 367 */ 368 ref public Matrix3d set(Matrix3d m) return { 369 m00 = m.m00; 370 m01 = m.m01; 371 m02 = m.m02; 372 m10 = m.m10; 373 m11 = m.m11; 374 m12 = m.m12; 375 m20 = m.m20; 376 m21 = m.m21; 377 m22 = m.m22; 378 return this; 379 } 380 381 /** 382 * Store the values of the transpose of the given matrix <code>m</code> into <code>this</code> matrix. 383 * 384 * @param m 385 * the matrix to copy the transposed values from 386 * @return this 387 */ 388 ref public Matrix3d setTransposed(Matrix3d m) return { 389 double nm10 = m.m01, nm12 = m.m21; 390 double nm20 = m.m02, nm21 = m.m12; 391 return this 392 ._m00(m.m00)._m01(m.m10)._m02(m.m20) 393 ._m10(nm10)._m11(m.m11)._m12(nm12) 394 ._m20(nm20)._m21(nm21)._m22(m.m22); 395 } 396 397 398 /** 399 * Set the elements of this matrix to the left 3x3 submatrix of <code>m</code>. 400 * 401 * @param m 402 * the matrix to copy the elements from 403 * @return this 404 */ 405 ref public Matrix3d set(Matrix4x3d m) return { 406 m00 = m.m00; 407 m01 = m.m01; 408 m02 = m.m02; 409 m10 = m.m10; 410 m11 = m.m11; 411 m12 = m.m12; 412 m20 = m.m20; 413 m21 = m.m21; 414 m22 = m.m22; 415 return this; 416 } 417 418 419 /** 420 * Set the elements of this matrix to the upper left 3x3 of the given {@link Matrix4d}. 421 * 422 * @param mat 423 * the {@link Matrix4d} to copy the values from 424 * @return this 425 */ 426 ref public Matrix3d set(Matrix4d mat) return { 427 m00 = mat.m00; 428 m01 = mat.m01; 429 m02 = mat.m02; 430 m10 = mat.m10; 431 m11 = mat.m11; 432 m12 = mat.m12; 433 m20 = mat.m20; 434 m21 = mat.m21; 435 m22 = mat.m22; 436 return this; 437 } 438 439 440 /** 441 * Set the upper left 2x2 submatrix of this {@link Matrix3d} to the given {@link Matrix2d} 442 * and the rest to identity. 443 * 444 * @see #Matrix3d(Matrix2d) 445 * 446 * @param mat 447 * the {@link Matrix2d} 448 * @return this 449 */ 450 ref public Matrix3d set(Matrix2d mat) return { 451 m00 = mat.m00; 452 m01 = mat.m01; 453 m02 = 0.0; 454 m10 = mat.m10; 455 m11 = mat.m11; 456 m12 = 0.0; 457 m20 = 0.0; 458 m21 = 0.0; 459 m22 = 1.0; 460 return this; 461 } 462 463 464 /** 465 * Set this matrix to be equivalent to the rotation specified by the given {@link AxisAngle4d}. 466 * 467 * @param axisAngle 468 * the {@link AxisAngle4d} 469 * @return this 470 */ 471 ref public Matrix3d set(AxisAngle4d axisAngle) return { 472 double x = axisAngle.x; 473 double y = axisAngle.y; 474 double z = axisAngle.z; 475 double angle = axisAngle.angle; 476 double invLength = Math.invsqrt(x*x + y*y + z*z); 477 x *= invLength; 478 y *= invLength; 479 z *= invLength; 480 double s = Math.sin(angle); 481 double c = Math.cosFromSin(s, angle); 482 double omc = 1.0 - c; 483 m00 = c + x*x*omc; 484 m11 = c + y*y*omc; 485 m22 = c + z*z*omc; 486 double tmp1 = x*y*omc; 487 double tmp2 = z*s; 488 m10 = tmp1 - tmp2; 489 m01 = tmp1 + tmp2; 490 tmp1 = x*z*omc; 491 tmp2 = y*s; 492 m20 = tmp1 + tmp2; 493 m02 = tmp1 - tmp2; 494 tmp1 = y*z*omc; 495 tmp2 = x*s; 496 m21 = tmp1 - tmp2; 497 m12 = tmp1 + tmp2; 498 return this; 499 } 500 501 /** 502 * Set this matrix to a rotation - and possibly scaling - equivalent to the given quaternion. 503 * <p> 504 * This method is equivalent to calling: <code>rotation(q)</code> 505 * <p> 506 * Reference: <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/">http://www.euclideanspace.com/</a> 507 * 508 * @see #rotation(Quaterniond) 509 * 510 * @param q 511 * the quaternion 512 * @return this 513 */ 514 ref public Matrix3d set(Quaterniond q) return { 515 return rotation(q); 516 } 517 518 /** 519 * Multiply this matrix by the supplied matrix. 520 * This matrix will be the left one. 521 * <p> 522 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the <code>right</code> matrix, 523 * then the new matrix will be <code>M * R</code>. So when transforming a 524 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 525 * transformation of the right matrix will be applied first! 526 * 527 * @param right 528 * the right operand 529 * @return this 530 */ 531 ref public Matrix3d mul(Matrix3d right) return { 532 mul(right, this); 533 return this; 534 } 535 536 public Matrix3d mul(Matrix3d right, ref Matrix3d dest) { 537 double nm00 = Math.fma(m00, right.m00, Math.fma(m10, right.m01, m20 * right.m02)); 538 double nm01 = Math.fma(m01, right.m00, Math.fma(m11, right.m01, m21 * right.m02)); 539 double nm02 = Math.fma(m02, right.m00, Math.fma(m12, right.m01, m22 * right.m02)); 540 double nm10 = Math.fma(m00, right.m10, Math.fma(m10, right.m11, m20 * right.m12)); 541 double nm11 = Math.fma(m01, right.m10, Math.fma(m11, right.m11, m21 * right.m12)); 542 double nm12 = Math.fma(m02, right.m10, Math.fma(m12, right.m11, m22 * right.m12)); 543 double nm20 = Math.fma(m00, right.m20, Math.fma(m10, right.m21, m20 * right.m22)); 544 double nm21 = Math.fma(m01, right.m20, Math.fma(m11, right.m21, m21 * right.m22)); 545 double nm22 = Math.fma(m02, right.m20, Math.fma(m12, right.m21, m22 * right.m22)); 546 dest.m00 = nm00; 547 dest.m01 = nm01; 548 dest.m02 = nm02; 549 dest.m10 = nm10; 550 dest.m11 = nm11; 551 dest.m12 = nm12; 552 dest.m20 = nm20; 553 dest.m21 = nm21; 554 dest.m22 = nm22; 555 return dest; 556 } 557 558 /** 559 * Pre-multiply this matrix by the supplied <code>left</code> matrix and store the result in <code>this</code>. 560 * <p> 561 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the <code>left</code> matrix, 562 * then the new matrix will be <code>L * M</code>. So when transforming a 563 * vector <code>v</code> with the new matrix by using <code>L * M * v</code>, the 564 * transformation of <code>this</code> matrix will be applied first! 565 * 566 * @param left 567 * the left operand of the matrix multiplication 568 * @return this 569 */ 570 ref public Matrix3d mulLocal(Matrix3d left) return { 571 mulLocal(left, this); 572 return this; 573 } 574 575 public Matrix3d mulLocal(Matrix3d left, ref Matrix3d dest) { 576 double nm00 = left.m00 * m00 + left.m10 * m01 + left.m20 * m02; 577 double nm01 = left.m01 * m00 + left.m11 * m01 + left.m21 * m02; 578 double nm02 = left.m02 * m00 + left.m12 * m01 + left.m22 * m02; 579 double nm10 = left.m00 * m10 + left.m10 * m11 + left.m20 * m12; 580 double nm11 = left.m01 * m10 + left.m11 * m11 + left.m21 * m12; 581 double nm12 = left.m02 * m10 + left.m12 * m11 + left.m22 * m12; 582 double nm20 = left.m00 * m20 + left.m10 * m21 + left.m20 * m22; 583 double nm21 = left.m01 * m20 + left.m11 * m21 + left.m21 * m22; 584 double nm22 = left.m02 * m20 + left.m12 * m21 + left.m22 * m22; 585 dest.m00 = nm00; 586 dest.m01 = nm01; 587 dest.m02 = nm02; 588 dest.m10 = nm10; 589 dest.m11 = nm11; 590 dest.m12 = nm12; 591 dest.m20 = nm20; 592 dest.m21 = nm21; 593 dest.m22 = nm22; 594 return dest; 595 } 596 597 598 /** 599 * Set the values within this matrix to the supplied double values. The result looks like this: 600 * <p> 601 * m00, m10, m20<br> 602 * m01, m11, m21<br> 603 * m02, m12, m22<br> 604 * 605 * @param m00 606 * the new value of m00 607 * @param m01 608 * the new value of m01 609 * @param m02 610 * the new value of m02 611 * @param m10 612 * the new value of m10 613 * @param m11 614 * the new value of m11 615 * @param m12 616 * the new value of m12 617 * @param m20 618 * the new value of m20 619 * @param m21 620 * the new value of m21 621 * @param m22 622 * the new value of m22 623 * @return this 624 */ 625 ref public Matrix3d set(double m00, double m01, double m02, 626 double m10, double m11, double m12, 627 double m20, double m21, double m22) return { 628 this.m00 = m00; 629 this.m01 = m01; 630 this.m02 = m02; 631 this.m10 = m10; 632 this.m11 = m11; 633 this.m12 = m12; 634 this.m20 = m20; 635 this.m21 = m21; 636 this.m22 = m22; 637 return this; 638 } 639 640 /** 641 * Set the values in this matrix based on the supplied double array. The result looks like this: 642 * <p> 643 * 0, 3, 6<br> 644 * 1, 4, 7<br> 645 * 2, 5, 8<br> 646 * <p> 647 * Only uses the first 9 values, all others are ignored. 648 * 649 * @param m 650 * the array to read the matrix values from 651 * @return this 652 */ 653 ref public Matrix3d set(double[] m) return { 654 m00 = m[0]; 655 m01 = m[1]; 656 m02 = m[2]; 657 m10 = m[3]; 658 m11 = m[4]; 659 m12 = m[5]; 660 m20 = m[6]; 661 m21 = m[7]; 662 m22 = m[8]; 663 return this; 664 } 665 666 667 public double determinant() { 668 return (m00 * m11 - m01 * m10) * m22 669 + (m02 * m10 - m00 * m12) * m21 670 + (m01 * m12 - m02 * m11) * m20; 671 } 672 673 /** 674 * Invert this matrix. 675 * 676 * @return this 677 */ 678 ref public Matrix3d invert() return { 679 invert(this); 680 return this; 681 } 682 683 public Matrix3d invert(ref Matrix3d dest) { 684 double a = Math.fma(m00, m11, -m01 * m10); 685 double b = Math.fma(m02, m10, -m00 * m12); 686 double c = Math.fma(m01, m12, -m02 * m11); 687 double d = Math.fma(a, m22, Math.fma(b, m21, c * m20)); 688 double s = 1.0 / d; 689 double nm00 = Math.fma(m11, m22, -m21 * m12) * s; 690 double nm01 = Math.fma(m21, m02, -m01 * m22) * s; 691 double nm02 = c * s; 692 double nm10 = Math.fma(m20, m12, -m10 * m22) * s; 693 double nm11 = Math.fma(m00, m22, -m20 * m02) * s; 694 double nm12 = b * s; 695 double nm20 = Math.fma(m10, m21, -m20 * m11) * s; 696 double nm21 = Math.fma(m20, m01, -m00 * m21) * s; 697 double nm22 = a * s; 698 dest.m00 = nm00; 699 dest.m01 = nm01; 700 dest.m02 = nm02; 701 dest.m10 = nm10; 702 dest.m11 = nm11; 703 dest.m12 = nm12; 704 dest.m20 = nm20; 705 dest.m21 = nm21; 706 dest.m22 = nm22; 707 return dest; 708 } 709 710 /** 711 * Transpose this matrix. 712 * 713 * @return this 714 */ 715 ref public Matrix3d transpose() return { 716 transpose(this); 717 return this; 718 } 719 720 public Matrix3d transpose(ref Matrix3d dest) { 721 dest.set(m00, m10, m20, 722 m01, m11, m21, 723 m02, m12, m22); 724 return dest; 725 } 726 727 728 /** 729 * Get the current values of <code>this</code> matrix and store them into 730 * <code>dest</code>. 731 * <p> 732 * This is the reverse method of {@link #set(Matrix3d)} and allows to obtain 733 * intermediate calculation results when chaining multiple transformations. 734 * 735 * @see #set(Matrix3d) 736 * 737 * @param dest 738 * the destination matrix 739 * @return the passed in destination 740 */ 741 public Matrix3d get(ref Matrix3d dest) { 742 return dest.set(this); 743 } 744 745 public Quaterniond getUnnormalizedRotation(ref Quaterniond dest) { 746 return dest.setFromUnnormalized(this); 747 } 748 749 public Quaterniond getNormalizedRotation(ref Quaterniond dest) { 750 return dest.setFromNormalized(this); 751 } 752 753 754 public double[] get(double[] arr, int offset) { 755 arr[offset+0] = m00; 756 arr[offset+1] = m01; 757 arr[offset+2] = m02; 758 arr[offset+3] = m10; 759 arr[offset+4] = m11; 760 arr[offset+5] = m12; 761 arr[offset+6] = m20; 762 arr[offset+7] = m21; 763 arr[offset+8] = m22; 764 return arr; 765 } 766 767 public double[] get(double[] arr) { 768 return get(arr, 0); 769 } 770 771 772 /** 773 * Set the three columns of this matrix to the supplied vectors, respectively. 774 * 775 * @param col0 776 * the first column 777 * @param col1 778 * the second column 779 * @param col2 780 * the third column 781 * @return this 782 */ 783 ref public Matrix3d set(Vector3d col0, 784 Vector3d col1, 785 Vector3d col2) return { 786 this.m00 = col0.x; 787 this.m01 = col0.y; 788 this.m02 = col0.z; 789 this.m10 = col1.x; 790 this.m11 = col1.y; 791 this.m12 = col1.z; 792 this.m20 = col2.x; 793 this.m21 = col2.y; 794 this.m22 = col2.z; 795 return this; 796 } 797 798 /** 799 * Set all the values within this matrix to 0. 800 * 801 * @return this 802 */ 803 ref public Matrix3d zero() return { 804 m00 = 0.0; 805 m01 = 0.0; 806 m02 = 0.0; 807 m10 = 0.0; 808 m11 = 0.0; 809 m12 = 0.0; 810 m20 = 0.0; 811 m21 = 0.0; 812 m22 = 0.0; 813 return this; 814 } 815 816 /** 817 * Set this matrix to the identity. 818 * 819 * @return this 820 */ 821 ref public Matrix3d identity() return { 822 m00 = 1.0; 823 m01 = 0.0; 824 m02 = 0.0; 825 m10 = 0.0; 826 m11 = 1.0; 827 m12 = 0.0; 828 m20 = 0.0; 829 m21 = 0.0; 830 m22 = 1.0; 831 return this; 832 } 833 834 /** 835 * Set this matrix to be a simple scale matrix, which scales all axes uniformly by the given factor. 836 * <p> 837 * The resulting matrix can be multiplied against another transformation 838 * matrix to obtain an additional scaling. 839 * <p> 840 * In order to post-multiply a scaling transformation directly to a 841 * matrix, use {@link #scale(double) scale()} instead. 842 * 843 * @see #scale(double) 844 * 845 * @param factor 846 * the scale factor in x, y and z 847 * @return this 848 */ 849 ref public Matrix3d scaling(double factor) return { 850 m00 = factor; 851 m01 = 0.0; 852 m02 = 0.0; 853 m10 = 0.0; 854 m11 = factor; 855 m12 = 0.0; 856 m20 = 0.0; 857 m21 = 0.0; 858 m22 = factor; 859 return this; 860 } 861 862 /** 863 * Set this matrix to be a simple scale matrix. 864 * 865 * @param x 866 * the scale in x 867 * @param y 868 * the scale in y 869 * @param z 870 * the scale in z 871 * @return this 872 */ 873 ref public Matrix3d scaling(double x, double y, double z) return { 874 m00 = x; 875 m01 = 0.0; 876 m02 = 0.0; 877 m10 = 0.0; 878 m11 = y; 879 m12 = 0.0; 880 m20 = 0.0; 881 m21 = 0.0; 882 m22 = z; 883 return this; 884 } 885 886 /** 887 * Set this matrix to be a simple scale matrix which scales the base axes by <code>xyz.x</code>, <code>xyz.y</code> and <code>xyz.z</code> respectively. 888 * <p> 889 * The resulting matrix can be multiplied against another transformation 890 * matrix to obtain an additional scaling. 891 * <p> 892 * In order to post-multiply a scaling transformation directly to a 893 * matrix use {@link #scale(Vector3d) scale()} instead. 894 * 895 * @see #scale(Vector3d) 896 * 897 * @param xyz 898 * the scale in x, y and z respectively 899 * @return this 900 */ 901 ref public Matrix3d scaling(Vector3d xyz) return { 902 m00 = xyz.x; 903 m01 = 0.0; 904 m02 = 0.0; 905 m10 = 0.0; 906 m11 = xyz.y; 907 m12 = 0.0; 908 m20 = 0.0; 909 m21 = 0.0; 910 m22 = xyz.z; 911 return this; 912 } 913 914 public Matrix3d scale(Vector3d xyz, ref Matrix3d dest) { 915 return scale(xyz.x, xyz.y, xyz.z, dest); 916 } 917 918 /** 919 * Apply scaling to this matrix by scaling the base axes by the given <code>xyz.x</code>, 920 * <code>xyz.y</code> and <code>xyz.z</code> factors, respectively. 921 * <p> 922 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 923 * then the new matrix will be <code>M * S</code>. So when transforming a 924 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 925 * scaling will be applied first! 926 * 927 * @param xyz 928 * the factors of the x, y and z component, respectively 929 * @return this 930 */ 931 ref public Matrix3d scale(Vector3d xyz) return { 932 scale(xyz.x, xyz.y, xyz.z, this); 933 return this; 934 } 935 936 public Matrix3d scale(double x, double y, double z, ref Matrix3d dest) { 937 // scale matrix elements: 938 // m00 = x, m11 = y, m22 = z 939 // all others = 0 940 dest.m00 = m00 * x; 941 dest.m01 = m01 * x; 942 dest.m02 = m02 * x; 943 dest.m10 = m10 * y; 944 dest.m11 = m11 * y; 945 dest.m12 = m12 * y; 946 dest.m20 = m20 * z; 947 dest.m21 = m21 * z; 948 dest.m22 = m22 * z; 949 return dest; 950 } 951 952 /** 953 * Apply scaling to this matrix by scaling the base axes by the given x, 954 * y and z factors. 955 * <p> 956 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 957 * then the new matrix will be <code>M * S</code>. So when transforming a 958 * vector <code>v</code> with the new matrix by using <code>M * S * v</code> 959 * , the scaling will be applied first! 960 * 961 * @param x 962 * the factor of the x component 963 * @param y 964 * the factor of the y component 965 * @param z 966 * the factor of the z component 967 * @return this 968 */ 969 ref public Matrix3d scale(double x, double y, double z) return { 970 scale(x, y, z, this); 971 return this; 972 } 973 974 public Matrix3d scale(double xyz, ref Matrix3d dest) { 975 return scale(xyz, xyz, xyz, dest); 976 } 977 978 /** 979 * Apply scaling to this matrix by uniformly scaling all base axes by the given <code>xyz</code> factor. 980 * <p> 981 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 982 * then the new matrix will be <code>M * S</code>. So when transforming a 983 * vector <code>v</code> with the new matrix by using <code>M * S * v</code> 984 * , the scaling will be applied first! 985 * 986 * @see #scale(double, double, double) 987 * 988 * @param xyz 989 * the factor for all components 990 * @return this 991 */ 992 ref public Matrix3d scale(double xyz) return { 993 return scale(xyz, xyz, xyz); 994 } 995 996 public Matrix3d scaleLocal(double x, double y, double z, ref Matrix3d dest) { 997 double nm00 = x * m00; 998 double nm01 = y * m01; 999 double nm02 = z * m02; 1000 double nm10 = x * m10; 1001 double nm11 = y * m11; 1002 double nm12 = z * m12; 1003 double nm20 = x * m20; 1004 double nm21 = y * m21; 1005 double nm22 = z * m22; 1006 dest.m00 = nm00; 1007 dest.m01 = nm01; 1008 dest.m02 = nm02; 1009 dest.m10 = nm10; 1010 dest.m11 = nm11; 1011 dest.m12 = nm12; 1012 dest.m20 = nm20; 1013 dest.m21 = nm21; 1014 dest.m22 = nm22; 1015 return dest; 1016 } 1017 1018 /** 1019 * Pre-multiply scaling to this matrix by scaling the base axes by the given x, 1020 * y and z factors. 1021 * <p> 1022 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 1023 * then the new matrix will be <code>S * M</code>. So when transforming a 1024 * vector <code>v</code> with the new matrix by using <code>S * M * v</code>, the 1025 * scaling will be applied last! 1026 * 1027 * @param x 1028 * the factor of the x component 1029 * @param y 1030 * the factor of the y component 1031 * @param z 1032 * the factor of the z component 1033 * @return this 1034 */ 1035 ref public Matrix3d scaleLocal(double x, double y, double z) return { 1036 scaleLocal(x, y, z, this); 1037 return this; 1038 } 1039 1040 /** 1041 * Set this matrix to a rotation matrix which rotates the given radians about a given axis. 1042 * <p> 1043 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1044 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1045 * When used with a left-handed coordinate system, the rotation is clockwise. 1046 * <p> 1047 * The resulting matrix can be multiplied against another transformation 1048 * matrix to obtain an additional rotation. 1049 * <p> 1050 * In order to post-multiply a rotation transformation directly to a 1051 * matrix, use {@link #rotate(double, Vector3d) rotate()} instead. 1052 * 1053 * @see #rotate(double, Vector3d) 1054 * 1055 * @param angle 1056 * the angle in radians 1057 * @param axis 1058 * the axis to rotate about (needs to be {@link Vector3d#normalize() normalized}) 1059 * @return this 1060 */ 1061 ref public Matrix3d rotation(double angle, Vector3d axis) return { 1062 return rotation(angle, axis.x, axis.y, axis.z); 1063 } 1064 1065 1066 1067 /** 1068 * Set this matrix to a rotation transformation using the given {@link AxisAngle4d}. 1069 * <p> 1070 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1071 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1072 * When used with a left-handed coordinate system, the rotation is clockwise. 1073 * <p> 1074 * The resulting matrix can be multiplied against another transformation 1075 * matrix to obtain an additional rotation. 1076 * <p> 1077 * In order to apply the rotation transformation to an existing transformation, 1078 * use {@link #rotate(AxisAngle4d) rotate()} instead. 1079 * <p> 1080 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 1081 * 1082 * @see #rotate(AxisAngle4d) 1083 * 1084 * @param axisAngle 1085 * the {@link AxisAngle4d} (needs to be {@link AxisAngle4d#normalize() normalized}) 1086 * @return this 1087 */ 1088 ref public Matrix3d rotation(AxisAngle4d axisAngle) return { 1089 return rotation(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z); 1090 } 1091 1092 /** 1093 * Set this matrix to a rotation matrix which rotates the given radians about a given axis. 1094 * <p> 1095 * The axis described by the three components needs to be a unit vector. 1096 * <p> 1097 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1098 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1099 * When used with a left-handed coordinate system, the rotation is clockwise. 1100 * <p> 1101 * The resulting matrix can be multiplied against another transformation 1102 * matrix to obtain an additional rotation. 1103 * <p> 1104 * In order to apply the rotation transformation to an existing transformation, 1105 * use {@link #rotate(double, double, double, double) rotate()} instead. 1106 * <p> 1107 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 1108 * 1109 * @see #rotate(double, double, double, double) 1110 * 1111 * @param angle 1112 * the angle in radians 1113 * @param x 1114 * the x-component of the rotation axis 1115 * @param y 1116 * the y-component of the rotation axis 1117 * @param z 1118 * the z-component of the rotation axis 1119 * @return this 1120 */ 1121 ref public Matrix3d rotation(double angle, double x, double y, double z) return { 1122 double sin = Math.sin(angle); 1123 double cos = Math.cosFromSin(sin, angle); 1124 double C = 1.0 - cos; 1125 double xy = x * y, xz = x * z, yz = y * z; 1126 m00 = cos + x * x * C; 1127 m10 = xy * C - z * sin; 1128 m20 = xz * C + y * sin; 1129 m01 = xy * C + z * sin; 1130 m11 = cos + y * y * C; 1131 m21 = yz * C - x * sin; 1132 m02 = xz * C - y * sin; 1133 m12 = yz * C + x * sin; 1134 m22 = cos + z * z * C; 1135 return this; 1136 } 1137 1138 /** 1139 * Set this matrix to a rotation transformation about the X axis. 1140 * <p> 1141 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1142 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1143 * When used with a left-handed coordinate system, the rotation is clockwise. 1144 * <p> 1145 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 1146 * 1147 * @param ang 1148 * the angle in radians 1149 * @return this 1150 */ 1151 ref public Matrix3d rotationX(double ang) return { 1152 double sin, cos; 1153 sin = Math.sin(ang); 1154 cos = Math.cosFromSin(sin, ang); 1155 m00 = 1.0; 1156 m01 = 0.0; 1157 m02 = 0.0; 1158 m10 = 0.0; 1159 m11 = cos; 1160 m12 = sin; 1161 m20 = 0.0; 1162 m21 = -sin; 1163 m22 = cos; 1164 return this; 1165 } 1166 1167 /** 1168 * Set this matrix to a rotation transformation about the Y axis. 1169 * <p> 1170 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1171 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1172 * When used with a left-handed coordinate system, the rotation is clockwise. 1173 * <p> 1174 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 1175 * 1176 * @param ang 1177 * the angle in radians 1178 * @return this 1179 */ 1180 ref public Matrix3d rotationY(double ang) return { 1181 double sin, cos; 1182 sin = Math.sin(ang); 1183 cos = Math.cosFromSin(sin, ang); 1184 m00 = cos; 1185 m01 = 0.0; 1186 m02 = -sin; 1187 m10 = 0.0; 1188 m11 = 1.0; 1189 m12 = 0.0; 1190 m20 = sin; 1191 m21 = 0.0; 1192 m22 = cos; 1193 return this; 1194 } 1195 1196 /** 1197 * Set this matrix to a rotation transformation about the Z axis. 1198 * <p> 1199 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1200 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1201 * When used with a left-handed coordinate system, the rotation is clockwise. 1202 * <p> 1203 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 1204 * 1205 * @param ang 1206 * the angle in radians 1207 * @return this 1208 */ 1209 ref public Matrix3d rotationZ(double ang) return { 1210 double sin, cos; 1211 sin = Math.sin(ang); 1212 cos = Math.cosFromSin(sin, ang); 1213 m00 = cos; 1214 m01 = sin; 1215 m02 = 0.0; 1216 m10 = -sin; 1217 m11 = cos; 1218 m12 = 0.0; 1219 m20 = 0.0; 1220 m21 = 0.0; 1221 m22 = 1.0; 1222 return this; 1223 } 1224 1225 /** 1226 * Set this matrix to a rotation of <code>angleX</code> radians about the X axis, followed by a rotation 1227 * of <code>angleY</code> radians about the Y axis and followed by a rotation of <code>angleZ</code> radians about the Z axis. 1228 * <p> 1229 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1230 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1231 * When used with a left-handed coordinate system, the rotation is clockwise. 1232 * <p> 1233 * This method is equivalent to calling: <code>rotationX(angleX).rotateY(angleY).rotateZ(angleZ)</code> 1234 * 1235 * @param angleX 1236 * the angle to rotate about X 1237 * @param angleY 1238 * the angle to rotate about Y 1239 * @param angleZ 1240 * the angle to rotate about Z 1241 * @return this 1242 */ 1243 ref public Matrix3d rotationXYZ(double angleX, double angleY, double angleZ) return { 1244 double sinX = Math.sin(angleX); 1245 double cosX = Math.cosFromSin(sinX, angleX); 1246 double sinY = Math.sin(angleY); 1247 double cosY = Math.cosFromSin(sinY, angleY); 1248 double sinZ = Math.sin(angleZ); 1249 double cosZ = Math.cosFromSin(sinZ, angleZ); 1250 double m_sinX = -sinX; 1251 double m_sinY = -sinY; 1252 double m_sinZ = -sinZ; 1253 1254 // rotateX 1255 double nm11 = cosX; 1256 double nm12 = sinX; 1257 double nm21 = m_sinX; 1258 double nm22 = cosX; 1259 // rotateY 1260 double nm00 = cosY; 1261 double nm01 = nm21 * m_sinY; 1262 double nm02 = nm22 * m_sinY; 1263 m20 = sinY; 1264 m21 = nm21 * cosY; 1265 m22 = nm22 * cosY; 1266 // rotateZ 1267 m00 = nm00 * cosZ; 1268 m01 = nm01 * cosZ + nm11 * sinZ; 1269 m02 = nm02 * cosZ + nm12 * sinZ; 1270 m10 = nm00 * m_sinZ; 1271 m11 = nm01 * m_sinZ + nm11 * cosZ; 1272 m12 = nm02 * m_sinZ + nm12 * cosZ; 1273 return this; 1274 } 1275 1276 /** 1277 * Set this matrix to a rotation of <code>angleZ</code> radians about the Z axis, followed by a rotation 1278 * of <code>angleY</code> radians about the Y axis and followed by a rotation of <code>angleX</code> radians about the X axis. 1279 * <p> 1280 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1281 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1282 * When used with a left-handed coordinate system, the rotation is clockwise. 1283 * <p> 1284 * This method is equivalent to calling: <code>rotationZ(angleZ).rotateY(angleY).rotateX(angleX)</code> 1285 * 1286 * @param angleZ 1287 * the angle to rotate about Z 1288 * @param angleY 1289 * the angle to rotate about Y 1290 * @param angleX 1291 * the angle to rotate about X 1292 * @return this 1293 */ 1294 ref public Matrix3d rotationZYX(double angleZ, double angleY, double angleX) return { 1295 double sinX = Math.sin(angleX); 1296 double cosX = Math.cosFromSin(sinX, angleX); 1297 double sinY = Math.sin(angleY); 1298 double cosY = Math.cosFromSin(sinY, angleY); 1299 double sinZ = Math.sin(angleZ); 1300 double cosZ = Math.cosFromSin(sinZ, angleZ); 1301 double m_sinZ = -sinZ; 1302 double m_sinY = -sinY; 1303 double m_sinX = -sinX; 1304 1305 // rotateZ 1306 double nm00 = cosZ; 1307 double nm01 = sinZ; 1308 double nm10 = m_sinZ; 1309 double nm11 = cosZ; 1310 // rotateY 1311 double nm20 = nm00 * sinY; 1312 double nm21 = nm01 * sinY; 1313 double nm22 = cosY; 1314 m00 = nm00 * cosY; 1315 m01 = nm01 * cosY; 1316 m02 = m_sinY; 1317 // rotateX 1318 m10 = nm10 * cosX + nm20 * sinX; 1319 m11 = nm11 * cosX + nm21 * sinX; 1320 m12 = nm22 * sinX; 1321 m20 = nm10 * m_sinX + nm20 * cosX; 1322 m21 = nm11 * m_sinX + nm21 * cosX; 1323 m22 = nm22 * cosX; 1324 return this; 1325 } 1326 1327 /** 1328 * Set this matrix to a rotation of <code>angleY</code> radians about the Y axis, followed by a rotation 1329 * of <code>angleX</code> radians about the X axis and followed by a rotation of <code>angleZ</code> radians about the Z axis. 1330 * <p> 1331 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1332 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1333 * When used with a left-handed coordinate system, the rotation is clockwise. 1334 * <p> 1335 * This method is equivalent to calling: <code>rotationY(angleY).rotateX(angleX).rotateZ(angleZ)</code> 1336 * 1337 * @param angleY 1338 * the angle to rotate about Y 1339 * @param angleX 1340 * the angle to rotate about X 1341 * @param angleZ 1342 * the angle to rotate about Z 1343 * @return this 1344 */ 1345 ref public Matrix3d rotationYXZ(double angleY, double angleX, double angleZ) return { 1346 double sinX = Math.sin(angleX); 1347 double cosX = Math.cosFromSin(sinX, angleX); 1348 double sinY = Math.sin(angleY); 1349 double cosY = Math.cosFromSin(sinY, angleY); 1350 double sinZ = Math.sin(angleZ); 1351 double cosZ = Math.cosFromSin(sinZ, angleZ); 1352 double m_sinY = -sinY; 1353 double m_sinX = -sinX; 1354 double m_sinZ = -sinZ; 1355 1356 // rotateY 1357 double nm00 = cosY; 1358 double nm02 = m_sinY; 1359 double nm20 = sinY; 1360 double nm22 = cosY; 1361 // rotateX 1362 double nm10 = nm20 * sinX; 1363 double nm11 = cosX; 1364 double nm12 = nm22 * sinX; 1365 m20 = nm20 * cosX; 1366 m21 = m_sinX; 1367 m22 = nm22 * cosX; 1368 // rotateZ 1369 m00 = nm00 * cosZ + nm10 * sinZ; 1370 m01 = nm11 * sinZ; 1371 m02 = nm02 * cosZ + nm12 * sinZ; 1372 m10 = nm00 * m_sinZ + nm10 * cosZ; 1373 m11 = nm11 * cosZ; 1374 m12 = nm02 * m_sinZ + nm12 * cosZ; 1375 return this; 1376 } 1377 1378 /** 1379 * Set this matrix to the rotation - and possibly scaling - transformation of the given {@link Quaterniond}. 1380 * <p> 1381 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1382 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1383 * When used with a left-handed coordinate system, the rotation is clockwise. 1384 * <p> 1385 * The resulting matrix can be multiplied against another transformation 1386 * matrix to obtain an additional rotation. 1387 * <p> 1388 * In order to apply the rotation transformation to an existing transformation, 1389 * use {@link #rotate(Quaterniond) rotate()} instead. 1390 * <p> 1391 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 1392 * 1393 * @see #rotate(Quaterniond) 1394 * 1395 * @param quat 1396 * the {@link Quaterniond} 1397 * @return this 1398 */ 1399 ref public Matrix3d rotation(Quaterniond quat) return { 1400 double w2 = quat.w * quat.w; 1401 double x2 = quat.x * quat.x; 1402 double y2 = quat.y * quat.y; 1403 double z2 = quat.z * quat.z; 1404 double zw = quat.z * quat.w, dzw = zw + zw; 1405 double xy = quat.x * quat.y, dxy = xy + xy; 1406 double xz = quat.x * quat.z, dxz = xz + xz; 1407 double yw = quat.y * quat.w, dyw = yw + yw; 1408 double yz = quat.y * quat.z, dyz = yz + yz; 1409 double xw = quat.x * quat.w, dxw = xw + xw; 1410 m00 = w2 + x2 - z2 - y2; 1411 m01 = dxy + dzw; 1412 m02 = dxz - dyw; 1413 m10 = -dzw + dxy; 1414 m11 = y2 - z2 + w2 - x2; 1415 m12 = dyz + dxw; 1416 m20 = dyw + dxz; 1417 m21 = dyz - dxw; 1418 m22 = z2 - y2 - x2 + w2; 1419 return this; 1420 } 1421 1422 1423 public Vector3d transform(Vector3d v) { 1424 return v.mul(this); 1425 } 1426 1427 public Vector3d transform(Vector3d v, ref Vector3d dest) { 1428 v.mul(this, dest); 1429 return dest; 1430 } 1431 1432 1433 public Vector3d transform(double x, double y, double z, ref Vector3d dest) { 1434 return dest.set(Math.fma(m00, x, Math.fma(m10, y, m20 * z)), 1435 Math.fma(m01, x, Math.fma(m11, y, m21 * z)), 1436 Math.fma(m02, x, Math.fma(m12, y, m22 * z))); 1437 } 1438 1439 public Vector3d transformTranspose(Vector3d v) { 1440 return v.mulTranspose(this); 1441 } 1442 1443 public Vector3d transformTranspose(Vector3d v, ref Vector3d dest) { 1444 return v.mulTranspose(this, dest); 1445 } 1446 1447 public Vector3d transformTranspose(double x, double y, double z, ref Vector3d dest) { 1448 return dest.set(Math.fma(m00, x, Math.fma(m01, y, m02 * z)), 1449 Math.fma(m10, x, Math.fma(m11, y, m12 * z)), 1450 Math.fma(m20, x, Math.fma(m21, y, m22 * z))); 1451 } 1452 1453 1454 public Matrix3d rotateX(double ang, ref Matrix3d dest) { 1455 double sin, cos; 1456 sin = Math.sin(ang); 1457 cos = Math.cosFromSin(sin, ang); 1458 double rm11 = cos; 1459 double rm21 = -sin; 1460 double rm12 = sin; 1461 double rm22 = cos; 1462 1463 // add temporaries for dependent values 1464 double nm10 = m10 * rm11 + m20 * rm12; 1465 double nm11 = m11 * rm11 + m21 * rm12; 1466 double nm12 = m12 * rm11 + m22 * rm12; 1467 // set non-dependent values directly 1468 dest.m20 = m10 * rm21 + m20 * rm22; 1469 dest.m21 = m11 * rm21 + m21 * rm22; 1470 dest.m22 = m12 * rm21 + m22 * rm22; 1471 // set other values 1472 dest.m10 = nm10; 1473 dest.m11 = nm11; 1474 dest.m12 = nm12; 1475 dest.m00 = m00; 1476 dest.m01 = m01; 1477 dest.m02 = m02; 1478 return dest; 1479 } 1480 1481 /** 1482 * Apply rotation about the X axis to this matrix by rotating the given amount of radians. 1483 * <p> 1484 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1485 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1486 * When used with a left-handed coordinate system, the rotation is clockwise. 1487 * <p> 1488 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 1489 * then the new matrix will be <code>M * R</code>. So when transforming a 1490 * vector <code>v</code> with the new matrix by using <code>M * R * v</code> 1491 * , the rotation will be applied first! 1492 * <p> 1493 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 1494 * 1495 * @param ang 1496 * the angle in radians 1497 * @return this 1498 */ 1499 ref public Matrix3d rotateX(double ang) return { 1500 rotateX(ang, this); 1501 return this; 1502 } 1503 1504 public Matrix3d rotateY(double ang, ref Matrix3d dest) { 1505 double sin, cos; 1506 sin = Math.sin(ang); 1507 cos = Math.cosFromSin(sin, ang); 1508 double rm00 = cos; 1509 double rm20 = sin; 1510 double rm02 = -sin; 1511 double rm22 = cos; 1512 1513 // add temporaries for dependent values 1514 double nm00 = m00 * rm00 + m20 * rm02; 1515 double nm01 = m01 * rm00 + m21 * rm02; 1516 double nm02 = m02 * rm00 + m22 * rm02; 1517 // set non-dependent values directly 1518 dest.m20 = m00 * rm20 + m20 * rm22; 1519 dest.m21 = m01 * rm20 + m21 * rm22; 1520 dest.m22 = m02 * rm20 + m22 * rm22; 1521 // set other values 1522 dest.m00 = nm00; 1523 dest.m01 = nm01; 1524 dest.m02 = nm02; 1525 dest.m10 = m10; 1526 dest.m11 = m11; 1527 dest.m12 = m12; 1528 return dest; 1529 } 1530 1531 /** 1532 * Apply rotation about the Y axis to this matrix by rotating the given amount of radians. 1533 * <p> 1534 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1535 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1536 * When used with a left-handed coordinate system, the rotation is clockwise. 1537 * <p> 1538 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 1539 * then the new matrix will be <code>M * R</code>. So when transforming a 1540 * vector <code>v</code> with the new matrix by using <code>M * R * v</code> 1541 * , the rotation will be applied first! 1542 * <p> 1543 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 1544 * 1545 * @param ang 1546 * the angle in radians 1547 * @return this 1548 */ 1549 ref public Matrix3d rotateY(double ang) return { 1550 rotateY(ang, this); 1551 return this; 1552 } 1553 1554 public Matrix3d rotateZ(double ang, ref Matrix3d dest) { 1555 double sin, cos; 1556 sin = Math.sin(ang); 1557 cos = Math.cosFromSin(sin, ang); 1558 double rm00 = cos; 1559 double rm10 = -sin; 1560 double rm01 = sin; 1561 double rm11 = cos; 1562 1563 // add temporaries for dependent values 1564 double nm00 = m00 * rm00 + m10 * rm01; 1565 double nm01 = m01 * rm00 + m11 * rm01; 1566 double nm02 = m02 * rm00 + m12 * rm01; 1567 // set non-dependent values directly 1568 dest.m10 = m00 * rm10 + m10 * rm11; 1569 dest.m11 = m01 * rm10 + m11 * rm11; 1570 dest.m12 = m02 * rm10 + m12 * rm11; 1571 // set other values 1572 dest.m00 = nm00; 1573 dest.m01 = nm01; 1574 dest.m02 = nm02; 1575 dest.m20 = m20; 1576 dest.m21 = m21; 1577 dest.m22 = m22; 1578 return dest; 1579 } 1580 1581 /** 1582 * Apply rotation about the Z axis to this matrix by rotating the given amount of radians. 1583 * <p> 1584 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1585 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1586 * When used with a left-handed coordinate system, the rotation is clockwise. 1587 * <p> 1588 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 1589 * then the new matrix will be <code>M * R</code>. So when transforming a 1590 * vector <code>v</code> with the new matrix by using <code>M * R * v</code> 1591 * , the rotation will be applied first! 1592 * <p> 1593 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 1594 * 1595 * @param ang 1596 * the angle in radians 1597 * @return this 1598 */ 1599 ref public Matrix3d rotateZ(double ang) return { 1600 rotateZ(ang, this); 1601 return this; 1602 } 1603 1604 /** 1605 * 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 1606 * followed by a rotation of <code>angleZ</code> radians about the Z axis. 1607 * <p> 1608 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1609 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1610 * When used with a left-handed coordinate system, the rotation is clockwise. 1611 * <p> 1612 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 1613 * then the new matrix will be <code>M * R</code>. So when transforming a 1614 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 1615 * rotation will be applied first! 1616 * <p> 1617 * This method is equivalent to calling: <code>rotateX(angleX).rotateY(angleY).rotateZ(angleZ)</code> 1618 * 1619 * @param angleX 1620 * the angle to rotate about X 1621 * @param angleY 1622 * the angle to rotate about Y 1623 * @param angleZ 1624 * the angle to rotate about Z 1625 * @return this 1626 */ 1627 ref public Matrix3d rotateXYZ(double angleX, double angleY, double angleZ) return { 1628 rotateXYZ(angleX, angleY, angleZ, this); 1629 return this; 1630 } 1631 1632 public Matrix3d rotateXYZ(double angleX, double angleY, double angleZ, ref Matrix3d dest) { 1633 double sinX = Math.sin(angleX); 1634 double cosX = Math.cosFromSin(sinX, angleX); 1635 double sinY = Math.sin(angleY); 1636 double cosY = Math.cosFromSin(sinY, angleY); 1637 double sinZ = Math.sin(angleZ); 1638 double cosZ = Math.cosFromSin(sinZ, angleZ); 1639 double m_sinX = -sinX; 1640 double m_sinY = -sinY; 1641 double m_sinZ = -sinZ; 1642 1643 // rotateX 1644 double nm10 = m10 * cosX + m20 * sinX; 1645 double nm11 = m11 * cosX + m21 * sinX; 1646 double nm12 = m12 * cosX + m22 * sinX; 1647 double nm20 = m10 * m_sinX + m20 * cosX; 1648 double nm21 = m11 * m_sinX + m21 * cosX; 1649 double nm22 = m12 * m_sinX + m22 * cosX; 1650 // rotateY 1651 double nm00 = m00 * cosY + nm20 * m_sinY; 1652 double nm01 = m01 * cosY + nm21 * m_sinY; 1653 double nm02 = m02 * cosY + nm22 * m_sinY; 1654 dest.m20 = m00 * sinY + nm20 * cosY; 1655 dest.m21 = m01 * sinY + nm21 * cosY; 1656 dest.m22 = m02 * sinY + nm22 * cosY; 1657 // rotateZ 1658 dest.m00 = nm00 * cosZ + nm10 * sinZ; 1659 dest.m01 = nm01 * cosZ + nm11 * sinZ; 1660 dest.m02 = nm02 * cosZ + nm12 * sinZ; 1661 dest.m10 = nm00 * m_sinZ + nm10 * cosZ; 1662 dest.m11 = nm01 * m_sinZ + nm11 * cosZ; 1663 dest.m12 = nm02 * m_sinZ + nm12 * cosZ; 1664 return dest; 1665 } 1666 1667 /** 1668 * 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 1669 * followed by a rotation of <code>angleX</code> radians about the X 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 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 1676 * then the new matrix will be <code>M * R</code>. So when transforming a 1677 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 1678 * rotation will be applied first! 1679 * <p> 1680 * This method is equivalent to calling: <code>rotateZ(angleZ).rotateY(angleY).rotateX(angleX)</code> 1681 * 1682 * @param angleZ 1683 * the angle to rotate about Z 1684 * @param angleY 1685 * the angle to rotate about Y 1686 * @param angleX 1687 * the angle to rotate about X 1688 * @return this 1689 */ 1690 ref public Matrix3d rotateZYX(double angleZ, double angleY, double angleX) return { 1691 rotateZYX(angleZ, angleY, angleX, this); 1692 return this; 1693 } 1694 1695 public Matrix3d rotateZYX(double angleZ, double angleY, double angleX, ref Matrix3d dest) { 1696 double sinX = Math.sin(angleX); 1697 double cosX = Math.cosFromSin(sinX, angleX); 1698 double sinY = Math.sin(angleY); 1699 double cosY = Math.cosFromSin(sinY, angleY); 1700 double sinZ = Math.sin(angleZ); 1701 double cosZ = Math.cosFromSin(sinZ, angleZ); 1702 double m_sinZ = -sinZ; 1703 double m_sinY = -sinY; 1704 double m_sinX = -sinX; 1705 1706 // rotateZ 1707 double nm00 = m00 * cosZ + m10 * sinZ; 1708 double nm01 = m01 * cosZ + m11 * sinZ; 1709 double nm02 = m02 * cosZ + m12 * sinZ; 1710 double nm10 = m00 * m_sinZ + m10 * cosZ; 1711 double nm11 = m01 * m_sinZ + m11 * cosZ; 1712 double nm12 = m02 * m_sinZ + m12 * cosZ; 1713 // rotateY 1714 double nm20 = nm00 * sinY + m20 * cosY; 1715 double nm21 = nm01 * sinY + m21 * cosY; 1716 double nm22 = nm02 * sinY + m22 * cosY; 1717 dest.m00 = nm00 * cosY + m20 * m_sinY; 1718 dest.m01 = nm01 * cosY + m21 * m_sinY; 1719 dest.m02 = nm02 * cosY + m22 * m_sinY; 1720 // rotateX 1721 dest.m10 = nm10 * cosX + nm20 * sinX; 1722 dest.m11 = nm11 * cosX + nm21 * sinX; 1723 dest.m12 = nm12 * cosX + nm22 * sinX; 1724 dest.m20 = nm10 * m_sinX + nm20 * cosX; 1725 dest.m21 = nm11 * m_sinX + nm21 * cosX; 1726 dest.m22 = nm12 * m_sinX + nm22 * cosX; 1727 return dest; 1728 } 1729 1730 /** 1731 * 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 1732 * followed by a rotation of <code>angles.z</code> radians about the Z axis. 1733 * <p> 1734 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1735 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1736 * When used with a left-handed coordinate system, the rotation is clockwise. 1737 * <p> 1738 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 1739 * then the new matrix will be <code>M * R</code>. So when transforming a 1740 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 1741 * rotation will be applied first! 1742 * <p> 1743 * This method is equivalent to calling: <code>rotateY(angles.y).rotateX(angles.x).rotateZ(angles.z)</code> 1744 * 1745 * @param angles 1746 * the Euler angles 1747 * @return this 1748 */ 1749 ref public Matrix3d rotateYXZ(Vector3d angles) return { 1750 return rotateYXZ(angles.y, angles.x, angles.z); 1751 } 1752 1753 /** 1754 * 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 1755 * followed by a rotation of <code>angleZ</code> radians about the Z axis. 1756 * <p> 1757 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1758 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1759 * When used with a left-handed coordinate system, the rotation is clockwise. 1760 * <p> 1761 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 1762 * then the new matrix will be <code>M * R</code>. So when transforming a 1763 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 1764 * rotation will be applied first! 1765 * <p> 1766 * This method is equivalent to calling: <code>rotateY(angleY).rotateX(angleX).rotateZ(angleZ)</code> 1767 * 1768 * @param angleY 1769 * the angle to rotate about Y 1770 * @param angleX 1771 * the angle to rotate about X 1772 * @param angleZ 1773 * the angle to rotate about Z 1774 * @return this 1775 */ 1776 ref public Matrix3d rotateYXZ(double angleY, double angleX, double angleZ) return { 1777 rotateYXZ(angleY, angleX, angleZ, this); 1778 return this; 1779 } 1780 1781 public Matrix3d rotateYXZ(double angleY, double angleX, double angleZ, ref Matrix3d dest) { 1782 double sinX = Math.sin(angleX); 1783 double cosX = Math.cosFromSin(sinX, angleX); 1784 double sinY = Math.sin(angleY); 1785 double cosY = Math.cosFromSin(sinY, angleY); 1786 double sinZ = Math.sin(angleZ); 1787 double cosZ = Math.cosFromSin(sinZ, angleZ); 1788 double m_sinY = -sinY; 1789 double m_sinX = -sinX; 1790 double m_sinZ = -sinZ; 1791 1792 // rotateY 1793 double nm20 = m00 * sinY + m20 * cosY; 1794 double nm21 = m01 * sinY + m21 * cosY; 1795 double nm22 = m02 * sinY + m22 * cosY; 1796 double nm00 = m00 * cosY + m20 * m_sinY; 1797 double nm01 = m01 * cosY + m21 * m_sinY; 1798 double nm02 = m02 * cosY + m22 * m_sinY; 1799 // rotateX 1800 double nm10 = m10 * cosX + nm20 * sinX; 1801 double nm11 = m11 * cosX + nm21 * sinX; 1802 double nm12 = m12 * cosX + nm22 * sinX; 1803 dest.m20 = m10 * m_sinX + nm20 * cosX; 1804 dest.m21 = m11 * m_sinX + nm21 * cosX; 1805 dest.m22 = m12 * m_sinX + nm22 * cosX; 1806 // rotateZ 1807 dest.m00 = nm00 * cosZ + nm10 * sinZ; 1808 dest.m01 = nm01 * cosZ + nm11 * sinZ; 1809 dest.m02 = nm02 * cosZ + nm12 * sinZ; 1810 dest.m10 = nm00 * m_sinZ + nm10 * cosZ; 1811 dest.m11 = nm01 * m_sinZ + nm11 * cosZ; 1812 dest.m12 = nm02 * m_sinZ + nm12 * cosZ; 1813 return dest; 1814 } 1815 1816 /** 1817 * Apply rotation to this matrix by rotating the given amount of radians 1818 * about the given axis specified as x, y and z components. 1819 * <p> 1820 * The axis described by the three components needs to be a unit vector. 1821 * <p> 1822 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1823 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1824 * When used with a left-handed coordinate system, the rotation is clockwise. 1825 * <p> 1826 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 1827 * then the new matrix will be <code>M * R</code>. So when transforming a 1828 * vector <code>v</code> with the new matrix by using <code>M * R * v</code> 1829 * , the rotation will be applied first! 1830 * <p> 1831 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 1832 * 1833 * @param ang 1834 * the angle in radians 1835 * @param x 1836 * the x component of the axis 1837 * @param y 1838 * the y component of the axis 1839 * @param z 1840 * the z component of the axis 1841 * @return this 1842 */ 1843 ref public Matrix3d rotate(double ang, double x, double y, double z) return { 1844 rotate(ang, x, y, z, this); 1845 return this; 1846 } 1847 1848 public Matrix3d rotate(double ang, double x, double y, double z, ref Matrix3d dest) { 1849 double s = Math.sin(ang); 1850 double c = Math.cosFromSin(s, ang); 1851 double C = 1.0 - c; 1852 1853 // rotation matrix elements: 1854 // m30, m31, m32, m03, m13, m23 = 0 1855 double xx = x * x, xy = x * y, xz = x * z; 1856 double yy = y * y, yz = y * z; 1857 double zz = z * z; 1858 double rm00 = xx * C + c; 1859 double rm01 = xy * C + z * s; 1860 double rm02 = xz * C - y * s; 1861 double rm10 = xy * C - z * s; 1862 double rm11 = yy * C + c; 1863 double rm12 = yz * C + x * s; 1864 double rm20 = xz * C + y * s; 1865 double rm21 = yz * C - x * s; 1866 double rm22 = zz * C + c; 1867 1868 // add temporaries for dependent values 1869 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 1870 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 1871 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 1872 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 1873 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 1874 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 1875 // set non-dependent values directly 1876 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 1877 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 1878 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 1879 // set other values 1880 dest.m00 = nm00; 1881 dest.m01 = nm01; 1882 dest.m02 = nm02; 1883 dest.m10 = nm10; 1884 dest.m11 = nm11; 1885 dest.m12 = nm12; 1886 return dest; 1887 } 1888 1889 /** 1890 * Pre-multiply a rotation to this matrix by rotating the given amount of radians 1891 * about the specified <code>(x, y, z)</code> axis and store the result in <code>dest</code>. 1892 * <p> 1893 * The axis described by the three components needs to be a unit vector. 1894 * <p> 1895 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1896 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1897 * When used with a left-handed coordinate system, the rotation is clockwise. 1898 * <p> 1899 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 1900 * then the new matrix will be <code>R * M</code>. So when transforming a 1901 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 1902 * rotation will be applied last! 1903 * <p> 1904 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 1905 * transformation, use {@link #rotation(double, double, double, double) rotation()}. 1906 * <p> 1907 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 1908 * 1909 * @see #rotation(double, double, double, double) 1910 * 1911 * @param ang 1912 * the angle in radians 1913 * @param x 1914 * the x component of the axis 1915 * @param y 1916 * the y component of the axis 1917 * @param z 1918 * the z component of the axis 1919 * @param dest 1920 * will hold the result 1921 * @return dest 1922 */ 1923 public Matrix3d rotateLocal(double ang, double x, double y, double z, ref Matrix3d dest) { 1924 double s = Math.sin(ang); 1925 double c = Math.cosFromSin(s, ang); 1926 double C = 1.0 - c; 1927 double xx = x * x, xy = x * y, xz = x * z; 1928 double yy = y * y, yz = y * z; 1929 double zz = z * z; 1930 double lm00 = xx * C + c; 1931 double lm01 = xy * C + z * s; 1932 double lm02 = xz * C - y * s; 1933 double lm10 = xy * C - z * s; 1934 double lm11 = yy * C + c; 1935 double lm12 = yz * C + x * s; 1936 double lm20 = xz * C + y * s; 1937 double lm21 = yz * C - x * s; 1938 double lm22 = zz * C + c; 1939 double nm00 = lm00 * m00 + lm10 * m01 + lm20 * m02; 1940 double nm01 = lm01 * m00 + lm11 * m01 + lm21 * m02; 1941 double nm02 = lm02 * m00 + lm12 * m01 + lm22 * m02; 1942 double nm10 = lm00 * m10 + lm10 * m11 + lm20 * m12; 1943 double nm11 = lm01 * m10 + lm11 * m11 + lm21 * m12; 1944 double nm12 = lm02 * m10 + lm12 * m11 + lm22 * m12; 1945 double nm20 = lm00 * m20 + lm10 * m21 + lm20 * m22; 1946 double nm21 = lm01 * m20 + lm11 * m21 + lm21 * m22; 1947 double nm22 = lm02 * m20 + lm12 * m21 + lm22 * m22; 1948 dest.m00 = nm00; 1949 dest.m01 = nm01; 1950 dest.m02 = nm02; 1951 dest.m10 = nm10; 1952 dest.m11 = nm11; 1953 dest.m12 = nm12; 1954 dest.m20 = nm20; 1955 dest.m21 = nm21; 1956 dest.m22 = nm22; 1957 return dest; 1958 } 1959 1960 /** 1961 * Pre-multiply a rotation to this matrix by rotating the given amount of radians 1962 * about the specified <code>(x, y, z)</code> axis. 1963 * <p> 1964 * The axis described by the three components needs to be a unit vector. 1965 * <p> 1966 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1967 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1968 * When used with a left-handed coordinate system, the rotation is clockwise. 1969 * <p> 1970 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 1971 * then the new matrix will be <code>R * M</code>. So when transforming a 1972 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 1973 * rotation will be applied last! 1974 * <p> 1975 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 1976 * transformation, use {@link #rotation(double, double, double, double) rotation()}. 1977 * <p> 1978 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 1979 * 1980 * @see #rotation(double, double, double, double) 1981 * 1982 * @param ang 1983 * the angle in radians 1984 * @param x 1985 * the x component of the axis 1986 * @param y 1987 * the y component of the axis 1988 * @param z 1989 * the z component of the axis 1990 * @return this 1991 */ 1992 ref public Matrix3d rotateLocal(double ang, double x, double y, double z) return { 1993 rotateLocal(ang, x, y, z, this); 1994 return this; 1995 } 1996 1997 /** 1998 * Pre-multiply a rotation around the X axis to this matrix by rotating the given amount of radians 1999 * about the X axis and store the result in <code>dest</code>. 2000 * <p> 2001 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2002 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2003 * When used with a left-handed coordinate system, the rotation is clockwise. 2004 * <p> 2005 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2006 * then the new matrix will be <code>R * M</code>. So when transforming a 2007 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2008 * rotation will be applied last! 2009 * <p> 2010 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2011 * transformation, use {@link #rotationX(double) rotationx}. 2012 * <p> 2013 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2014 * 2015 * @see #rotationX(double) 2016 * 2017 * @param ang 2018 * the angle in radians to rotate about the X axis 2019 * @param dest 2020 * will hold the result 2021 * @return dest 2022 */ 2023 public Matrix3d rotateLocalX(double ang, ref Matrix3d dest) { 2024 double sin = Math.sin(ang); 2025 double cos = Math.cosFromSin(sin, ang); 2026 double nm01 = cos * m01 - sin * m02; 2027 double nm02 = sin * m01 + cos * m02; 2028 double nm11 = cos * m11 - sin * m12; 2029 double nm12 = sin * m11 + cos * m12; 2030 double nm21 = cos * m21 - sin * m22; 2031 double nm22 = sin * m21 + cos * m22; 2032 dest.m00 = m00; 2033 dest.m01 = nm01; 2034 dest.m02 = nm02; 2035 dest.m10 = m10; 2036 dest.m11 = nm11; 2037 dest.m12 = nm12; 2038 dest.m20 = m20; 2039 dest.m21 = nm21; 2040 dest.m22 = nm22; 2041 return dest; 2042 } 2043 2044 /** 2045 * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the X axis. 2046 * <p> 2047 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2048 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2049 * When used with a left-handed coordinate system, the rotation is clockwise. 2050 * <p> 2051 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2052 * then the new matrix will be <code>R * M</code>. So when transforming a 2053 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2054 * rotation will be applied last! 2055 * <p> 2056 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2057 * transformation, use {@link #rotationX(double) rotationx}. 2058 * <p> 2059 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2060 * 2061 * @see #rotationX(double) 2062 * 2063 * @param ang 2064 * the angle in radians to rotate about the X axis 2065 * @return this 2066 */ 2067 ref public Matrix3d rotateLocalX(double ang) return { 2068 rotateLocalX(ang, this); 2069 return this; 2070 } 2071 2072 /** 2073 * Pre-multiply a rotation around the Y axis to this matrix by rotating the given amount of radians 2074 * about the Y axis and store the result in <code>dest</code>. 2075 * <p> 2076 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2077 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2078 * When used with a left-handed coordinate system, the rotation is clockwise. 2079 * <p> 2080 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2081 * then the new matrix will be <code>R * M</code>. So when transforming a 2082 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2083 * rotation will be applied last! 2084 * <p> 2085 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2086 * transformation, use {@link #rotationY(double) rotationy}. 2087 * <p> 2088 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2089 * 2090 * @see #rotationY(double) 2091 * 2092 * @param ang 2093 * the angle in radians to rotate about the Y axis 2094 * @param dest 2095 * will hold the result 2096 * @return dest 2097 */ 2098 public Matrix3d rotateLocalY(double ang, ref Matrix3d dest) { 2099 double sin = Math.sin(ang); 2100 double cos = Math.cosFromSin(sin, ang); 2101 double nm00 = cos * m00 + sin * m02; 2102 double nm02 = -sin * m00 + cos * m02; 2103 double nm10 = cos * m10 + sin * m12; 2104 double nm12 = -sin * m10 + cos * m12; 2105 double nm20 = cos * m20 + sin * m22; 2106 double nm22 = -sin * m20 + cos * m22; 2107 dest.m00 = nm00; 2108 dest.m01 = m01; 2109 dest.m02 = nm02; 2110 dest.m10 = nm10; 2111 dest.m11 = m11; 2112 dest.m12 = nm12; 2113 dest.m20 = nm20; 2114 dest.m21 = m21; 2115 dest.m22 = nm22; 2116 return dest; 2117 } 2118 2119 /** 2120 * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the Y axis. 2121 * <p> 2122 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2123 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2124 * When used with a left-handed coordinate system, the rotation is clockwise. 2125 * <p> 2126 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2127 * then the new matrix will be <code>R * M</code>. So when transforming a 2128 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2129 * rotation will be applied last! 2130 * <p> 2131 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2132 * transformation, use {@link #rotationY(double) rotationy}. 2133 * <p> 2134 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2135 * 2136 * @see #rotationY(double) 2137 * 2138 * @param ang 2139 * the angle in radians to rotate about the Y axis 2140 * @return this 2141 */ 2142 ref public Matrix3d rotateLocalY(double ang) return { 2143 rotateLocalY(ang, this); 2144 return this; 2145 } 2146 2147 /** 2148 * Pre-multiply a rotation around the Z axis to this matrix by rotating the given amount of radians 2149 * about the Z axis and store the result in <code>dest</code>. 2150 * <p> 2151 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2152 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2153 * When used with a left-handed coordinate system, the rotation is clockwise. 2154 * <p> 2155 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2156 * then the new matrix will be <code>R * M</code>. So when transforming a 2157 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2158 * rotation will be applied last! 2159 * <p> 2160 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2161 * transformation, use {@link #rotationZ(double) rotationz}. 2162 * <p> 2163 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2164 * 2165 * @see #rotationZ(double) 2166 * 2167 * @param ang 2168 * the angle in radians to rotate about the Z axis 2169 * @param dest 2170 * will hold the result 2171 * @return dest 2172 */ 2173 public Matrix3d rotateLocalZ(double ang, ref Matrix3d dest) { 2174 double sin = Math.sin(ang); 2175 double cos = Math.cosFromSin(sin, ang); 2176 double nm00 = cos * m00 - sin * m01; 2177 double nm01 = sin * m00 + cos * m01; 2178 double nm10 = cos * m10 - sin * m11; 2179 double nm11 = sin * m10 + cos * m11; 2180 double nm20 = cos * m20 - sin * m21; 2181 double nm21 = sin * m20 + cos * m21; 2182 dest.m00 = nm00; 2183 dest.m01 = nm01; 2184 dest.m02 = m02; 2185 dest.m10 = nm10; 2186 dest.m11 = nm11; 2187 dest.m12 = m12; 2188 dest.m20 = nm20; 2189 dest.m21 = nm21; 2190 dest.m22 = m22; 2191 return dest; 2192 } 2193 2194 /** 2195 * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the Z axis. 2196 * <p> 2197 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2198 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2199 * When used with a left-handed coordinate system, the rotation is clockwise. 2200 * <p> 2201 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2202 * then the new matrix will be <code>R * M</code>. So when transforming a 2203 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2204 * rotation will be applied last! 2205 * <p> 2206 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2207 * transformation, use {@link #rotationZ(double) rotationy}. 2208 * <p> 2209 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2210 * 2211 * @see #rotationY(double) 2212 * 2213 * @param ang 2214 * the angle in radians to rotate about the Z axis 2215 * @return this 2216 */ 2217 ref public Matrix3d rotateLocalZ(double ang) return { 2218 rotateLocalZ(ang, this); 2219 return this; 2220 } 2221 2222 /** 2223 * Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaterniond} to this matrix and store 2224 * the result in <code>dest</code>. 2225 * <p> 2226 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2227 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2228 * When used with a left-handed coordinate system, the rotation is clockwise. 2229 * <p> 2230 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 2231 * then the new matrix will be <code>Q * M</code>. So when transforming a 2232 * vector <code>v</code> with the new matrix by using <code>Q * M * v</code>, 2233 * the quaternion rotation will be applied last! 2234 * <p> 2235 * In order to set the matrix to a rotation transformation without pre-multiplying, 2236 * use {@link #rotation(Quaterniond)}. 2237 * <p> 2238 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 2239 * 2240 * @see #rotation(Quaterniond) 2241 * 2242 * @param quat 2243 * the {@link Quaterniond} 2244 * @param dest 2245 * will hold the result 2246 * @return dest 2247 */ 2248 public Matrix3d rotateLocal(Quaterniond quat, ref Matrix3d dest) { 2249 double w2 = quat.w * quat.w, x2 = quat.x * quat.x; 2250 double y2 = quat.y * quat.y, z2 = quat.z * quat.z; 2251 double zw = quat.z * quat.w, dzw = zw + zw, xy = quat.x * quat.y, dxy = xy + xy; 2252 double xz = quat.x * quat.z, dxz = xz + xz, yw = quat.y * quat.w, dyw = yw + yw; 2253 double yz = quat.y * quat.z, dyz = yz + yz, xw = quat.x * quat.w, dxw = xw + xw; 2254 double lm00 = w2 + x2 - z2 - y2; 2255 double lm01 = dxy + dzw; 2256 double lm02 = dxz - dyw; 2257 double lm10 = dxy - dzw; 2258 double lm11 = y2 - z2 + w2 - x2; 2259 double lm12 = dyz + dxw; 2260 double lm20 = dyw + dxz; 2261 double lm21 = dyz - dxw; 2262 double lm22 = z2 - y2 - x2 + w2; 2263 double nm00 = lm00 * m00 + lm10 * m01 + lm20 * m02; 2264 double nm01 = lm01 * m00 + lm11 * m01 + lm21 * m02; 2265 double nm02 = lm02 * m00 + lm12 * m01 + lm22 * m02; 2266 double nm10 = lm00 * m10 + lm10 * m11 + lm20 * m12; 2267 double nm11 = lm01 * m10 + lm11 * m11 + lm21 * m12; 2268 double nm12 = lm02 * m10 + lm12 * m11 + lm22 * m12; 2269 double nm20 = lm00 * m20 + lm10 * m21 + lm20 * m22; 2270 double nm21 = lm01 * m20 + lm11 * m21 + lm21 * m22; 2271 double nm22 = lm02 * m20 + lm12 * m21 + lm22 * m22; 2272 dest.m00 = nm00; 2273 dest.m01 = nm01; 2274 dest.m02 = nm02; 2275 dest.m10 = nm10; 2276 dest.m11 = nm11; 2277 dest.m12 = nm12; 2278 dest.m20 = nm20; 2279 dest.m21 = nm21; 2280 dest.m22 = nm22; 2281 return dest; 2282 } 2283 2284 /** 2285 * Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaterniond} to this matrix. 2286 * <p> 2287 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2288 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2289 * When used with a left-handed coordinate system, the rotation is clockwise. 2290 * <p> 2291 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 2292 * then the new matrix will be <code>Q * M</code>. So when transforming a 2293 * vector <code>v</code> with the new matrix by using <code>Q * M * v</code>, 2294 * the quaternion rotation will be applied last! 2295 * <p> 2296 * In order to set the matrix to a rotation transformation without pre-multiplying, 2297 * use {@link #rotation(Quaterniond)}. 2298 * <p> 2299 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 2300 * 2301 * @see #rotation(Quaterniond) 2302 * 2303 * @param quat 2304 * the {@link Quaterniond} 2305 * @return this 2306 */ 2307 ref public Matrix3d rotateLocal(Quaterniond quat) return { 2308 rotateLocal(quat, this); 2309 return this; 2310 } 2311 2312 2313 /** 2314 * Apply the rotation - and possibly scaling - transformation of the given {@link Quaterniond} to this matrix. 2315 * <p> 2316 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2317 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2318 * When used with a left-handed coordinate system, the rotation is clockwise. 2319 * <p> 2320 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 2321 * then the new matrix will be <code>M * Q</code>. So when transforming a 2322 * vector <code>v</code> with the new matrix by using <code>M * Q * v</code>, 2323 * the quaternion rotation will be applied first! 2324 * <p> 2325 * In order to set the matrix to a rotation transformation without post-multiplying, 2326 * use {@link #rotation(Quaterniond)}. 2327 * <p> 2328 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 2329 * 2330 * @see #rotation(Quaterniond) 2331 * 2332 * @param quat 2333 * the {@link Quaterniond} 2334 * @return this 2335 */ 2336 ref public Matrix3d rotate(Quaterniond quat) return { 2337 rotate(quat, this); 2338 return this; 2339 } 2340 2341 /** 2342 * Apply the rotation - and possibly scaling - transformation of the given {@link Quaterniond} to this matrix and store 2343 * the result in <code>dest</code>. 2344 * <p> 2345 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2346 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2347 * When used with a left-handed coordinate system, the rotation is clockwise. 2348 * <p> 2349 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 2350 * then the new matrix will be <code>M * Q</code>. So when transforming a 2351 * vector <code>v</code> with the new matrix by using <code>M * Q * v</code>, 2352 * the quaternion rotation will be applied first! 2353 * <p> 2354 * In order to set the matrix to a rotation transformation without post-multiplying, 2355 * use {@link #rotation(Quaterniond)}. 2356 * <p> 2357 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 2358 * 2359 * @see #rotation(Quaterniond) 2360 * 2361 * @param quat 2362 * the {@link Quaterniond} 2363 * @param dest 2364 * will hold the result 2365 * @return dest 2366 */ 2367 public Matrix3d rotate(Quaterniond quat, ref Matrix3d dest) { 2368 double w2 = quat.w * quat.w, x2 = quat.x * quat.x; 2369 double y2 = quat.y * quat.y, z2 = quat.z * quat.z; 2370 double zw = quat.z * quat.w, dzw = zw + zw, xy = quat.x * quat.y, dxy = xy + xy; 2371 double xz = quat.x * quat.z, dxz = xz + xz, yw = quat.y * quat.w, dyw = yw + yw; 2372 double yz = quat.y * quat.z, dyz = yz + yz, xw = quat.x * quat.w, dxw = xw + xw; 2373 double rm00 = w2 + x2 - z2 - y2; 2374 double rm01 = dxy + dzw; 2375 double rm02 = dxz - dyw; 2376 double rm10 = dxy - dzw; 2377 double rm11 = y2 - z2 + w2 - x2; 2378 double rm12 = dyz + dxw; 2379 double rm20 = dyw + dxz; 2380 double rm21 = dyz - dxw; 2381 double rm22 = z2 - y2 - x2 + w2; 2382 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 2383 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 2384 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 2385 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 2386 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 2387 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 2388 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 2389 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 2390 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 2391 dest.m00 = nm00; 2392 dest.m01 = nm01; 2393 dest.m02 = nm02; 2394 dest.m10 = nm10; 2395 dest.m11 = nm11; 2396 dest.m12 = nm12; 2397 return dest; 2398 } 2399 2400 /** 2401 * Apply a rotation transformation, rotating about the given {@link AxisAngle4d}, to this matrix. 2402 * <p> 2403 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2404 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2405 * When used with a left-handed coordinate system, the rotation is clockwise. 2406 * <p> 2407 * If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given {@link AxisAngle4d}, 2408 * then the new matrix will be <code>M * A</code>. So when transforming a 2409 * vector <code>v</code> with the new matrix by using <code>M * A * v</code>, 2410 * the {@link AxisAngle4d} rotation will be applied first! 2411 * <p> 2412 * In order to set the matrix to a rotation transformation without post-multiplying, 2413 * use {@link #rotation(AxisAngle4d)}. 2414 * <p> 2415 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 2416 * 2417 * @see #rotate(double, double, double, double) 2418 * @see #rotation(AxisAngle4d) 2419 * 2420 * @param axisAngle 2421 * the {@link AxisAngle4d} (needs to be {@link AxisAngle4d#normalize() normalized}) 2422 * @return this 2423 */ 2424 ref public Matrix3d rotate(AxisAngle4d axisAngle) return { 2425 return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z); 2426 } 2427 2428 /** 2429 * Apply a rotation transformation, rotating about the given {@link AxisAngle4d} and store the result in <code>dest</code>. 2430 * <p> 2431 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2432 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2433 * When used with a left-handed coordinate system, the rotation is clockwise. 2434 * <p> 2435 * If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given {@link AxisAngle4d}, 2436 * then the new matrix will be <code>M * A</code>. So when transforming a 2437 * vector <code>v</code> with the new matrix by using <code>M * A * v</code>, 2438 * the {@link AxisAngle4d} rotation will be applied first! 2439 * <p> 2440 * In order to set the matrix to a rotation transformation without post-multiplying, 2441 * use {@link #rotation(AxisAngle4d)}. 2442 * <p> 2443 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 2444 * 2445 * @see #rotate(double, double, double, double) 2446 * @see #rotation(AxisAngle4d) 2447 * 2448 * @param axisAngle 2449 * the {@link AxisAngle4d} (needs to be {@link AxisAngle4d#normalize() normalized}) 2450 * @param dest 2451 * will hold the result 2452 * @return dest 2453 */ 2454 public Matrix3d rotate(AxisAngle4d axisAngle, ref Matrix3d dest) { 2455 return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z, dest); 2456 } 2457 2458 /** 2459 * Apply a rotation transformation, rotating the given radians about the specified axis, to this matrix. 2460 * <p> 2461 * The axis described by the <code>axis</code> vector needs to be a unit vector. 2462 * <p> 2463 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2464 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2465 * When used with a left-handed coordinate system, the rotation is clockwise. 2466 * <p> 2467 * If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given angle and axis, 2468 * then the new matrix will be <code>M * A</code>. So when transforming a 2469 * vector <code>v</code> with the new matrix by using <code>M * A * v</code>, 2470 * the axis-angle rotation will be applied first! 2471 * <p> 2472 * In order to set the matrix to a rotation transformation without post-multiplying, 2473 * use {@link #rotation(double, Vector3d)}. 2474 * <p> 2475 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 2476 * 2477 * @see #rotate(double, double, double, double) 2478 * @see #rotation(double, Vector3d) 2479 * 2480 * @param angle 2481 * the angle in radians 2482 * @param axis 2483 * the rotation axis (needs to be {@link Vector3d#normalize() normalized}) 2484 * @return this 2485 */ 2486 ref public Matrix3d rotate(double angle, Vector3d axis) return { 2487 return rotate(angle, axis.x, axis.y, axis.z); 2488 } 2489 2490 /** 2491 * Apply a rotation transformation, rotating the given radians about the specified axis and store the result in <code>dest</code>. 2492 * <p> 2493 * The axis described by the <code>axis</code> vector needs to be a unit vector. 2494 * <p> 2495 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2496 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2497 * When used with a left-handed coordinate system, the rotation is clockwise. 2498 * <p> 2499 * If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given axis and angle, 2500 * then the new matrix will be <code>M * A</code>. So when transforming a 2501 * vector <code>v</code> with the new matrix by using <code>M * A * v</code>, 2502 * the axis-angle rotation will be applied first! 2503 * <p> 2504 * In order to set the matrix to a rotation transformation without post-multiplying, 2505 * use {@link #rotation(double, Vector3d)}. 2506 * <p> 2507 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 2508 * 2509 * @see #rotate(double, double, double, double) 2510 * @see #rotation(double, Vector3d) 2511 * 2512 * @param angle 2513 * the angle in radians 2514 * @param axis 2515 * the rotation axis (needs to be {@link Vector3d#normalize() normalized}) 2516 * @param dest 2517 * will hold the result 2518 * @return dest 2519 */ 2520 public Matrix3d rotate(double angle, Vector3d axis, ref Matrix3d dest) { 2521 return rotate(angle, axis.x, axis.y, axis.z, dest); 2522 } 2523 2524 public Vector3d getRow(int row, ref Vector3d dest) { 2525 switch (row) { 2526 case 0: 2527 return dest.set(m00, m10, m20); 2528 case 1: 2529 return dest.set(m01, m11, m21); 2530 case 2: 2531 return dest.set(m02, m12, m22); 2532 default: 2533 return dest; 2534 } 2535 } 2536 2537 /** 2538 * Set the row at the given <code>row</code> index, starting with <code>0</code>. 2539 * 2540 * @param row 2541 * the row index in <code>[0..2]</code> 2542 * @param src 2543 * the row components to set 2544 * @return this 2545 * @throws IndexOutOfBoundsException if <code>row</code> is not in <code>[0..2]</code> 2546 */ 2547 ref public Matrix3d setRow(int row, Vector3d src) return { 2548 return setRow(row, src.x, src.y, src.z); 2549 } 2550 2551 /** 2552 * Set the row at the given <code>row</code> index, starting with <code>0</code>. 2553 * 2554 * @param row 2555 * the column index in <code>[0..2]</code> 2556 * @param x 2557 * the first element in the row 2558 * @param y 2559 * the second element in the row 2560 * @param z 2561 * the third element in the row 2562 * @return this 2563 * @throws IndexOutOfBoundsException if <code>row</code> is not in <code>[0..2]</code> 2564 */ 2565 ref public Matrix3d setRow(int row, double x, double y, double z) return { 2566 switch (row) { 2567 case 0: 2568 this.m00 = x; 2569 this.m10 = y; 2570 this.m20 = z; 2571 break; 2572 case 1: 2573 this.m01 = x; 2574 this.m11 = y; 2575 this.m21 = z; 2576 break; 2577 case 2: 2578 this.m02 = x; 2579 this.m12 = y; 2580 this.m22 = z; 2581 break; 2582 default: {} 2583 } 2584 return this; 2585 } 2586 2587 public Vector3d getColumn(int column, ref Vector3d dest){ 2588 switch (column) { 2589 case 0: 2590 return dest.set(m00, m01, m02); 2591 case 1: 2592 return dest.set(m10, m11, m12); 2593 case 2: 2594 return dest.set(m20, m21, m22); 2595 default: 2596 return dest; 2597 } 2598 } 2599 2600 /** 2601 * Set the column at the given <code>column</code> index, starting with <code>0</code>. 2602 * 2603 * @param column 2604 * the column index in <code>[0..2]</code> 2605 * @param src 2606 * the column components to set 2607 * @return this 2608 * @throws IndexOutOfBoundsException if <code>column</code> is not in <code>[0..2]</code> 2609 */ 2610 ref public Matrix3d setColumn(int column, Vector3d src) return { 2611 return setColumn(column, src.x, src.y, src.z); 2612 } 2613 2614 /** 2615 * Set the column at the given <code>column</code> index, starting with <code>0</code>. 2616 * 2617 * @param column 2618 * the column index in <code>[0..2]</code> 2619 * @param x 2620 * the first element in the column 2621 * @param y 2622 * the second element in the column 2623 * @param z 2624 * the third element in the column 2625 * @return this 2626 * @throws IndexOutOfBoundsException if <code>column</code> is not in <code>[0..2]</code> 2627 */ 2628 ref public Matrix3d setColumn(int column, double x, double y, double z) return { 2629 switch (column) { 2630 case 0: 2631 this.m00 = x; 2632 this.m01 = y; 2633 this.m02 = z; 2634 break; 2635 case 1: 2636 this.m10 = x; 2637 this.m11 = y; 2638 this.m12 = z; 2639 break; 2640 case 2: 2641 this.m20 = x; 2642 this.m21 = y; 2643 this.m22 = z; 2644 break; 2645 default: {} 2646 } 2647 return this; 2648 } 2649 2650 public double get(int column, int row) { 2651 return MemUtil.get(this, column, row); 2652 } 2653 2654 /** 2655 * Set the matrix element at the given column and row to the specified value. 2656 * 2657 * @param column 2658 * the colum index in <code>[0..2]</code> 2659 * @param row 2660 * the row index in <code>[0..2]</code> 2661 * @param value 2662 * the value 2663 * @return this 2664 */ 2665 ref public Matrix3d set(int column, int row, double value) return { 2666 MemUtil.set(this, column, row, value); 2667 return this; 2668 2669 } 2670 2671 public double getRowColumn(int row, int column) { 2672 return MemUtil.get(this, column, row); 2673 } 2674 2675 /** 2676 * Set the matrix element at the given row and column to the specified value. 2677 * 2678 * @param row 2679 * the row index in <code>[0..2]</code> 2680 * @param column 2681 * the colum index in <code>[0..2]</code> 2682 * @param value 2683 * the value 2684 * @return this 2685 */ 2686 ref public Matrix3d setRowColumn(int row, int column, double value) return { 2687 MemUtil.set(this, column, row, value); 2688 return this; 2689 } 2690 2691 /** 2692 * Set <code>this</code> matrix to its own normal matrix. 2693 * <p> 2694 * The normal matrix of <code>m</code> is the transpose of the inverse of <code>m</code>. 2695 * <p> 2696 * Please note that, if <code>this</code> is an orthogonal matrix or a matrix whose columns are orthogonal vectors, 2697 * then this method <i>need not</i> be invoked, since in that case <code>this</code> itself is its normal matrix. 2698 * In this case, use {@link #set(Matrix3d)} to set a given Matrix3f to this matrix. 2699 * 2700 * @see #set(Matrix3d) 2701 * 2702 * @return this 2703 */ 2704 ref public Matrix3d normal() return { 2705 normal(this); 2706 return this; 2707 } 2708 2709 /** 2710 * Compute a normal matrix from <code>this</code> matrix and store it into <code>dest</code>. 2711 * <p> 2712 * The normal matrix of <code>m</code> is the transpose of the inverse of <code>m</code>. 2713 * <p> 2714 * Please note that, if <code>this</code> is an orthogonal matrix or a matrix whose columns are orthogonal vectors, 2715 * then this method <i>need not</i> be invoked, since in that case <code>this</code> itself is its normal matrix. 2716 * In this case, use {@link #set(Matrix3d)} to set a given Matrix3d to this matrix. 2717 * 2718 * @see #set(Matrix3d) 2719 * 2720 * @param dest 2721 * will hold the result 2722 * @return dest 2723 */ 2724 public Matrix3d normal(ref Matrix3d dest) { 2725 double m00m11 = m00 * m11; 2726 double m01m10 = m01 * m10; 2727 double m02m10 = m02 * m10; 2728 double m00m12 = m00 * m12; 2729 double m01m12 = m01 * m12; 2730 double m02m11 = m02 * m11; 2731 double det = (m00m11 - m01m10) * m22 + (m02m10 - m00m12) * m21 + (m01m12 - m02m11) * m20; 2732 double s = 1.0 / det; 2733 /* Invert and transpose in one go */ 2734 double nm00 = (m11 * m22 - m21 * m12) * s; 2735 double nm01 = (m20 * m12 - m10 * m22) * s; 2736 double nm02 = (m10 * m21 - m20 * m11) * s; 2737 double nm10 = (m21 * m02 - m01 * m22) * s; 2738 double nm11 = (m00 * m22 - m20 * m02) * s; 2739 double nm12 = (m20 * m01 - m00 * m21) * s; 2740 double nm20 = (m01m12 - m02m11) * s; 2741 double nm21 = (m02m10 - m00m12) * s; 2742 double nm22 = (m00m11 - m01m10) * s; 2743 dest.m00 = nm00; 2744 dest.m01 = nm01; 2745 dest.m02 = nm02; 2746 dest.m10 = nm10; 2747 dest.m11 = nm11; 2748 dest.m12 = nm12; 2749 dest.m20 = nm20; 2750 dest.m21 = nm21; 2751 dest.m22 = nm22; 2752 return dest; 2753 } 2754 2755 /** 2756 * Compute the cofactor matrix of <code>this</code>. 2757 * <p> 2758 * The cofactor matrix can be used instead of {@link #normal()} to transform normals 2759 * when the orientation of the normals with respect to the surface should be preserved. 2760 * 2761 * @return this 2762 */ 2763 ref public Matrix3d cofactor() return { 2764 cofactor(this); 2765 return this; 2766 } 2767 2768 /** 2769 * Compute the cofactor matrix of <code>this</code> and store it into <code>dest</code>. 2770 * <p> 2771 * The cofactor matrix can be used instead of {@link #normal(Matrix3d)} to transform normals 2772 * when the orientation of the normals with respect to the surface should be preserved. 2773 * 2774 * @param dest 2775 * will hold the result 2776 * @return dest 2777 */ 2778 public Matrix3d cofactor(ref Matrix3d dest) { 2779 double nm00 = m11 * m22 - m21 * m12; 2780 double nm01 = m20 * m12 - m10 * m22; 2781 double nm02 = m10 * m21 - m20 * m11; 2782 double nm10 = m21 * m02 - m01 * m22; 2783 double nm11 = m00 * m22 - m20 * m02; 2784 double nm12 = m20 * m01 - m00 * m21; 2785 double nm20 = m01 * m12 - m11 * m02; 2786 double nm21 = m02 * m10 - m12 * m00; 2787 double nm22 = m00 * m11 - m10 * m01; 2788 dest.m00 = nm00; 2789 dest.m01 = nm01; 2790 dest.m02 = nm02; 2791 dest.m10 = nm10; 2792 dest.m11 = nm11; 2793 dest.m12 = nm12; 2794 dest.m20 = nm20; 2795 dest.m21 = nm21; 2796 dest.m22 = nm22; 2797 return dest; 2798 } 2799 2800 /** 2801 * Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code>. 2802 * <p> 2803 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix, 2804 * then the new matrix will be <code>M * L</code>. So when transforming a 2805 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the 2806 * lookalong rotation transformation will be applied first! 2807 * <p> 2808 * In order to set the matrix to a lookalong transformation without post-multiplying it, 2809 * use {@link #setLookAlong(Vector3d, Vector3d) setLookAlong()}. 2810 * 2811 * @see #lookAlong(double, double, double, double, double, double) 2812 * @see #setLookAlong(Vector3d, Vector3d) 2813 * 2814 * @param dir 2815 * the direction in space to look along 2816 * @param up 2817 * the direction of 'up' 2818 * @return this 2819 */ 2820 ref public Matrix3d lookAlong(Vector3d dir, Vector3d up) return { 2821 lookAlong(dir.x, dir.y, dir.z, up.x, up.y, up.z, this); 2822 return this; 2823 } 2824 2825 /** 2826 * Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code> 2827 * and store the result in <code>dest</code>. 2828 * <p> 2829 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix, 2830 * then the new matrix will be <code>M * L</code>. So when transforming a 2831 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the 2832 * lookalong rotation transformation will be applied first! 2833 * <p> 2834 * In order to set the matrix to a lookalong transformation without post-multiplying it, 2835 * use {@link #setLookAlong(Vector3d, Vector3d) setLookAlong()}. 2836 * 2837 * @see #lookAlong(double, double, double, double, double, double) 2838 * @see #setLookAlong(Vector3d, Vector3d) 2839 * 2840 * @param dir 2841 * the direction in space to look along 2842 * @param up 2843 * the direction of 'up' 2844 * @param dest 2845 * will hold the result 2846 * @return dest 2847 */ 2848 public Matrix3d lookAlong(Vector3d dir, Vector3d up, ref Matrix3d dest) { 2849 return lookAlong(dir.x, dir.y, dir.z, up.x, up.y, up.z, dest); 2850 } 2851 2852 /** 2853 * Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code> 2854 * and store the result in <code>dest</code>. 2855 * <p> 2856 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix, 2857 * then the new matrix will be <code>M * L</code>. So when transforming a 2858 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the 2859 * lookalong rotation transformation will be applied first! 2860 * <p> 2861 * In order to set the matrix to a lookalong transformation without post-multiplying it, 2862 * use {@link #setLookAlong(double, double, double, double, double, double) setLookAlong()} 2863 * 2864 * @see #setLookAlong(double, double, double, double, double, double) 2865 * 2866 * @param dirX 2867 * the x-coordinate of the direction to look along 2868 * @param dirY 2869 * the y-coordinate of the direction to look along 2870 * @param dirZ 2871 * the z-coordinate of the direction to look along 2872 * @param upX 2873 * the x-coordinate of the up vector 2874 * @param upY 2875 * the y-coordinate of the up vector 2876 * @param upZ 2877 * the z-coordinate of the up vector 2878 * @param dest 2879 * will hold the result 2880 * @return dest 2881 */ 2882 public Matrix3d lookAlong(double dirX, double dirY, double dirZ, 2883 double upX, double upY, double upZ, ref Matrix3d dest) { 2884 // Normalize direction 2885 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 2886 dirX *= -invDirLength; 2887 dirY *= -invDirLength; 2888 dirZ *= -invDirLength; 2889 // left = up x direction 2890 double leftX, leftY, leftZ; 2891 leftX = upY * dirZ - upZ * dirY; 2892 leftY = upZ * dirX - upX * dirZ; 2893 leftZ = upX * dirY - upY * dirX; 2894 // normalize left 2895 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 2896 leftX *= invLeftLength; 2897 leftY *= invLeftLength; 2898 leftZ *= invLeftLength; 2899 // up = direction x left 2900 double upnX = dirY * leftZ - dirZ * leftY; 2901 double upnY = dirZ * leftX - dirX * leftZ; 2902 double upnZ = dirX * leftY - dirY * leftX; 2903 2904 // calculate right matrix elements 2905 double rm00 = leftX; 2906 double rm01 = upnX; 2907 double rm02 = dirX; 2908 double rm10 = leftY; 2909 double rm11 = upnY; 2910 double rm12 = dirY; 2911 double rm20 = leftZ; 2912 double rm21 = upnZ; 2913 double rm22 = dirZ; 2914 2915 // perform optimized matrix multiplication 2916 // introduce temporaries for dependent results 2917 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 2918 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 2919 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 2920 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 2921 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 2922 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 2923 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 2924 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 2925 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 2926 // set the rest of the matrix elements 2927 dest.m00 = nm00; 2928 dest.m01 = nm01; 2929 dest.m02 = nm02; 2930 dest.m10 = nm10; 2931 dest.m11 = nm11; 2932 dest.m12 = nm12; 2933 return dest; 2934 } 2935 2936 /** 2937 * Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code>. 2938 * <p> 2939 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix, 2940 * then the new matrix will be <code>M * L</code>. So when transforming a 2941 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the 2942 * lookalong rotation transformation will be applied first! 2943 * <p> 2944 * In order to set the matrix to a lookalong transformation without post-multiplying it, 2945 * use {@link #setLookAlong(double, double, double, double, double, double) setLookAlong()} 2946 * 2947 * @see #setLookAlong(double, double, double, double, double, double) 2948 * 2949 * @param dirX 2950 * the x-coordinate of the direction to look along 2951 * @param dirY 2952 * the y-coordinate of the direction to look along 2953 * @param dirZ 2954 * the z-coordinate of the direction to look along 2955 * @param upX 2956 * the x-coordinate of the up vector 2957 * @param upY 2958 * the y-coordinate of the up vector 2959 * @param upZ 2960 * the z-coordinate of the up vector 2961 * @return this 2962 */ 2963 ref public Matrix3d lookAlong(double dirX, double dirY, double dirZ, 2964 double upX, double upY, double upZ) return { 2965 lookAlong(dirX, dirY, dirZ, upX, upY, upZ, this); 2966 return this; 2967 } 2968 2969 /** 2970 * Set this matrix to a rotation transformation to make <code>-z</code> 2971 * point along <code>dir</code>. 2972 * <p> 2973 * In order to apply the lookalong transformation to any previous existing transformation, 2974 * use {@link #lookAlong(Vector3d, Vector3d)}. 2975 * 2976 * @see #setLookAlong(Vector3d, Vector3d) 2977 * @see #lookAlong(Vector3d, Vector3d) 2978 * 2979 * @param dir 2980 * the direction in space to look along 2981 * @param up 2982 * the direction of 'up' 2983 * @return this 2984 */ 2985 ref public Matrix3d setLookAlong(Vector3d dir, Vector3d up) return { 2986 return setLookAlong(dir.x, dir.y, dir.z, up.x, up.y, up.z); 2987 } 2988 2989 /** 2990 * Set this matrix to a rotation transformation to make <code>-z</code> 2991 * point along <code>dir</code>. 2992 * <p> 2993 * In order to apply the lookalong transformation to any previous existing transformation, 2994 * use {@link #lookAlong(double, double, double, double, double, double) lookAlong()} 2995 * 2996 * @see #setLookAlong(double, double, double, double, double, double) 2997 * @see #lookAlong(double, double, double, double, double, double) 2998 * 2999 * @param dirX 3000 * the x-coordinate of the direction to look along 3001 * @param dirY 3002 * the y-coordinate of the direction to look along 3003 * @param dirZ 3004 * the z-coordinate of the direction to look along 3005 * @param upX 3006 * the x-coordinate of the up vector 3007 * @param upY 3008 * the y-coordinate of the up vector 3009 * @param upZ 3010 * the z-coordinate of the up vector 3011 * @return this 3012 */ 3013 ref public Matrix3d setLookAlong(double dirX, double dirY, double dirZ, 3014 double upX, double upY, double upZ) return { 3015 // Normalize direction 3016 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 3017 dirX *= -invDirLength; 3018 dirY *= -invDirLength; 3019 dirZ *= -invDirLength; 3020 // left = up x direction 3021 double leftX, leftY, leftZ; 3022 leftX = upY * dirZ - upZ * dirY; 3023 leftY = upZ * dirX - upX * dirZ; 3024 leftZ = upX * dirY - upY * dirX; 3025 // normalize left 3026 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 3027 leftX *= invLeftLength; 3028 leftY *= invLeftLength; 3029 leftZ *= invLeftLength; 3030 // up = direction x left 3031 double upnX = dirY * leftZ - dirZ * leftY; 3032 double upnY = dirZ * leftX - dirX * leftZ; 3033 double upnZ = dirX * leftY - dirY * leftX; 3034 3035 m00 = leftX; 3036 m01 = upnX; 3037 m02 = dirX; 3038 m10 = leftY; 3039 m11 = upnY; 3040 m12 = dirY; 3041 m20 = leftZ; 3042 m21 = upnZ; 3043 m22 = dirZ; 3044 3045 return this; 3046 } 3047 3048 public Vector3d getScale(ref Vector3d dest) { 3049 dest.x = Math.sqrt(m00 * m00 + m01 * m01 + m02 * m02); 3050 dest.y = Math.sqrt(m10 * m10 + m11 * m11 + m12 * m12); 3051 dest.z = Math.sqrt(m20 * m20 + m21 * m21 + m22 * m22); 3052 return dest; 3053 } 3054 3055 public Vector3d positiveZ(Vector3d dir) { 3056 dir.x = m10 * m21 - m11 * m20; 3057 dir.y = m20 * m01 - m21 * m00; 3058 dir.z = m00 * m11 - m01 * m10; 3059 return dir.normalize(dir); 3060 } 3061 3062 public Vector3d normalizedPositiveZ(Vector3d dir) { 3063 dir.x = m02; 3064 dir.y = m12; 3065 dir.z = m22; 3066 return dir; 3067 } 3068 3069 public Vector3d positiveX(Vector3d dir) { 3070 dir.x = m11 * m22 - m12 * m21; 3071 dir.y = m02 * m21 - m01 * m22; 3072 dir.z = m01 * m12 - m02 * m11; 3073 return dir.normalize(dir); 3074 } 3075 3076 public Vector3d normalizedPositiveX(Vector3d dir) { 3077 dir.x = m00; 3078 dir.y = m10; 3079 dir.z = m20; 3080 return dir; 3081 } 3082 3083 public Vector3d positiveY(Vector3d dir) { 3084 dir.x = m12 * m20 - m10 * m22; 3085 dir.y = m00 * m22 - m02 * m20; 3086 dir.z = m02 * m10 - m00 * m12; 3087 return dir.normalize(dir); 3088 } 3089 3090 public Vector3d normalizedPositiveY(Vector3d dir) { 3091 dir.x = m01; 3092 dir.y = m11; 3093 dir.z = m21; 3094 return dir; 3095 } 3096 3097 public int hashCode() { 3098 immutable int prime = 31; 3099 int result = 1; 3100 long temp; 3101 temp = Math.doubleToLongBits(m00); 3102 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 3103 temp = Math.doubleToLongBits(m01); 3104 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 3105 temp = Math.doubleToLongBits(m02); 3106 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 3107 temp = Math.doubleToLongBits(m10); 3108 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 3109 temp = Math.doubleToLongBits(m11); 3110 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 3111 temp = Math.doubleToLongBits(m12); 3112 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 3113 temp = Math.doubleToLongBits(m20); 3114 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 3115 temp = Math.doubleToLongBits(m21); 3116 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 3117 temp = Math.doubleToLongBits(m22); 3118 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 3119 return result; 3120 } 3121 3122 public bool equals(Matrix3d m, double delta) { 3123 if (this == m) 3124 return true; 3125 if (!Math.equals(m00, m.m00, delta)) 3126 return false; 3127 if (!Math.equals(m01, m.m01, delta)) 3128 return false; 3129 if (!Math.equals(m02, m.m02, delta)) 3130 return false; 3131 if (!Math.equals(m10, m.m10, delta)) 3132 return false; 3133 if (!Math.equals(m11, m.m11, delta)) 3134 return false; 3135 if (!Math.equals(m12, m.m12, delta)) 3136 return false; 3137 if (!Math.equals(m20, m.m20, delta)) 3138 return false; 3139 if (!Math.equals(m21, m.m21, delta)) 3140 return false; 3141 if (!Math.equals(m22, m.m22, delta)) 3142 return false; 3143 return true; 3144 } 3145 3146 /** 3147 * Exchange the values of <code>this</code> matrix with the given <code>other</code> matrix. 3148 * 3149 * @param other 3150 * the other matrix to exchange the values with 3151 * @return this 3152 */ 3153 ref public Matrix3d swap(ref Matrix3d other) return { 3154 double tmp; 3155 tmp = m00; m00 = other.m00; other.m00 = tmp; 3156 tmp = m01; m01 = other.m01; other.m01 = tmp; 3157 tmp = m02; m02 = other.m02; other.m02 = tmp; 3158 tmp = m10; m10 = other.m10; other.m10 = tmp; 3159 tmp = m11; m11 = other.m11; other.m11 = tmp; 3160 tmp = m12; m12 = other.m12; other.m12 = tmp; 3161 tmp = m20; m20 = other.m20; other.m20 = tmp; 3162 tmp = m21; m21 = other.m21; other.m21 = tmp; 3163 tmp = m22; m22 = other.m22; other.m22 = tmp; 3164 return this; 3165 } 3166 3167 /** 3168 * Component-wise add <code>this</code> and <code>other</code>. 3169 * 3170 * @param other 3171 * the other addend 3172 * @return this 3173 */ 3174 ref public Matrix3d add(Matrix3d other) return { 3175 add(other, this); 3176 return this; 3177 } 3178 3179 public Matrix3d add(Matrix3d other, ref Matrix3d dest) { 3180 dest.m00 = m00 + other.m00; 3181 dest.m01 = m01 + other.m01; 3182 dest.m02 = m02 + other.m02; 3183 dest.m10 = m10 + other.m10; 3184 dest.m11 = m11 + other.m11; 3185 dest.m12 = m12 + other.m12; 3186 dest.m20 = m20 + other.m20; 3187 dest.m21 = m21 + other.m21; 3188 dest.m22 = m22 + other.m22; 3189 return dest; 3190 } 3191 3192 /** 3193 * Component-wise subtract <code>subtrahend</code> from <code>this</code>. 3194 * 3195 * @param subtrahend 3196 * the subtrahend 3197 * @return this 3198 */ 3199 ref public Matrix3d sub(Matrix3d subtrahend) return { 3200 sub(subtrahend, this); 3201 return this; 3202 } 3203 3204 public Matrix3d sub(Matrix3d subtrahend, ref Matrix3d dest) { 3205 dest.m00 = m00 - subtrahend.m00; 3206 dest.m01 = m01 - subtrahend.m01; 3207 dest.m02 = m02 - subtrahend.m02; 3208 dest.m10 = m10 - subtrahend.m10; 3209 dest.m11 = m11 - subtrahend.m11; 3210 dest.m12 = m12 - subtrahend.m12; 3211 dest.m20 = m20 - subtrahend.m20; 3212 dest.m21 = m21 - subtrahend.m21; 3213 dest.m22 = m22 - subtrahend.m22; 3214 return dest; 3215 } 3216 3217 /** 3218 * Component-wise multiply <code>this</code> by <code>other</code>. 3219 * 3220 * @param other 3221 * the other matrix 3222 * @return this 3223 */ 3224 ref public Matrix3d mulComponentWise(Matrix3d other) return { 3225 mulComponentWise(other, this); 3226 return this; 3227 } 3228 3229 public Matrix3d mulComponentWise(Matrix3d other, ref Matrix3d dest) { 3230 dest.m00 = m00 * other.m00; 3231 dest.m01 = m01 * other.m01; 3232 dest.m02 = m02 * other.m02; 3233 dest.m10 = m10 * other.m10; 3234 dest.m11 = m11 * other.m11; 3235 dest.m12 = m12 * other.m12; 3236 dest.m20 = m20 * other.m20; 3237 dest.m21 = m21 * other.m21; 3238 dest.m22 = m22 * other.m22; 3239 return dest; 3240 } 3241 3242 /** 3243 * Set this matrix to a skew-symmetric matrix using the following layout: 3244 * <pre> 3245 * 0, a, -b 3246 * -a, 0, c 3247 * b, -c, 0 3248 * </pre> 3249 * 3250 * Reference: <a href="https://en.wikipedia.org/wiki/Skew-symmetric_matrix">https://en.wikipedia.org</a> 3251 * 3252 * @param a 3253 * the value used for the matrix elements m01 and m10 3254 * @param b 3255 * the value used for the matrix elements m02 and m20 3256 * @param c 3257 * the value used for the matrix elements m12 and m21 3258 * @return this 3259 */ 3260 ref public Matrix3d setSkewSymmetric(double a, double b, double c) return { 3261 m00 = m11 = m22 = 0; 3262 m01 = -a; 3263 m02 = b; 3264 m10 = a; 3265 m12 = -c; 3266 m20 = -b; 3267 m21 = c; 3268 return this; 3269 } 3270 3271 /** 3272 * Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code> 3273 * and store the result in <code>this</code>. 3274 * <p> 3275 * 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> 3276 * then the result is <code>other</code>. 3277 * 3278 * @param other 3279 * the other matrix 3280 * @param t 3281 * the interpolation factor between 0.0 and 1.0 3282 * @return this 3283 */ 3284 ref public Matrix3d lerp(Matrix3d other, double t) return { 3285 lerp(other, t, this); 3286 return this; 3287 } 3288 3289 public Matrix3d lerp(Matrix3d other, double t, ref Matrix3d dest) { 3290 dest.m00 = Math.fma(other.m00 - m00, t, m00); 3291 dest.m01 = Math.fma(other.m01 - m01, t, m01); 3292 dest.m02 = Math.fma(other.m02 - m02, t, m02); 3293 dest.m10 = Math.fma(other.m10 - m10, t, m10); 3294 dest.m11 = Math.fma(other.m11 - m11, t, m11); 3295 dest.m12 = Math.fma(other.m12 - m12, t, m12); 3296 dest.m20 = Math.fma(other.m20 - m20, t, m20); 3297 dest.m21 = Math.fma(other.m21 - m21, t, m21); 3298 dest.m22 = Math.fma(other.m22 - m22, t, m22); 3299 return dest; 3300 } 3301 3302 /** 3303 * Apply a model transformation to this matrix for a right-handed coordinate system, 3304 * that aligns the local <code>+Z</code> axis with <code>direction</code> 3305 * and store the result in <code>dest</code>. 3306 * <p> 3307 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 3308 * then the new matrix will be <code>M * L</code>. So when transforming a 3309 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 3310 * the lookat transformation will be applied first! 3311 * <p> 3312 * In order to set the matrix to a rotation transformation without post-multiplying it, 3313 * use {@link #rotationTowards(Vector3d, Vector3d) rotationTowards()}. 3314 * <p> 3315 * This method is equivalent to calling: <code>mul(new Matrix3d().lookAlong(new Vector3d(dir).negate(), up).invert(), dest)</code> 3316 * 3317 * @see #rotateTowards(double, double, double, double, double, double, Matrix3d) 3318 * @see #rotationTowards(Vector3d, Vector3d) 3319 * 3320 * @param direction 3321 * the direction to rotate towards 3322 * @param up 3323 * the model's up vector 3324 * @param dest 3325 * will hold the result 3326 * @return dest 3327 */ 3328 public Matrix3d rotateTowards(Vector3d direction, Vector3d up, ref Matrix3d dest) { 3329 return rotateTowards(direction.x, direction.y, direction.z, up.x, up.y, up.z, dest); 3330 } 3331 3332 /** 3333 * Apply a model transformation to this matrix for a right-handed coordinate system, 3334 * that aligns the local <code>+Z</code> axis with <code>direction</code>. 3335 * <p> 3336 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 3337 * then the new matrix will be <code>M * L</code>. So when transforming a 3338 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 3339 * the lookat transformation will be applied first! 3340 * <p> 3341 * In order to set the matrix to a rotation transformation without post-multiplying it, 3342 * use {@link #rotationTowards(Vector3d, Vector3d) rotationTowards()}. 3343 * <p> 3344 * This method is equivalent to calling: <code>mul(new Matrix3d().lookAlong(new Vector3d(dir).negate(), up).invert())</code> 3345 * 3346 * @see #rotateTowards(double, double, double, double, double, double) 3347 * @see #rotationTowards(Vector3d, Vector3d) 3348 * 3349 * @param direction 3350 * the direction to orient towards 3351 * @param up 3352 * the up vector 3353 * @return this 3354 */ 3355 ref public Matrix3d rotateTowards(Vector3d direction, Vector3d up) return { 3356 rotateTowards(direction.x, direction.y, direction.z, up.x, up.y, up.z, this); 3357 return this; 3358 } 3359 3360 /** 3361 * Apply a model transformation to this matrix for a right-handed coordinate system, 3362 * that aligns the local <code>+Z</code> axis with <code>direction</code>. 3363 * <p> 3364 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 3365 * then the new matrix will be <code>M * L</code>. So when transforming a 3366 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 3367 * the lookat transformation will be applied first! 3368 * <p> 3369 * In order to set the matrix to a rotation transformation without post-multiplying it, 3370 * use {@link #rotationTowards(double, double, double, double, double, double) rotationTowards()}. 3371 * <p> 3372 * This method is equivalent to calling: <code>mul(new Matrix3d().lookAlong(-dirX, -dirY, -dirZ, upX, upY, upZ).invert())</code> 3373 * 3374 * @see #rotateTowards(Vector3d, Vector3d) 3375 * @see #rotationTowards(double, double, double, double, double, double) 3376 * 3377 * @param dirX 3378 * the x-coordinate of the direction to rotate towards 3379 * @param dirY 3380 * the y-coordinate of the direction to rotate towards 3381 * @param dirZ 3382 * the z-coordinate of the direction to rotate towards 3383 * @param upX 3384 * the x-coordinate of the up vector 3385 * @param upY 3386 * the y-coordinate of the up vector 3387 * @param upZ 3388 * the z-coordinate of the up vector 3389 * @return this 3390 */ 3391 ref public Matrix3d rotateTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ) return { 3392 rotateTowards(dirX, dirY, dirZ, upX, upY, upZ, this); 3393 return this; 3394 } 3395 3396 /** 3397 * Apply a model transformation to this matrix for a right-handed coordinate system, 3398 * that aligns the local <code>+Z</code> axis with <code>dir</code> 3399 * and store the result in <code>dest</code>. 3400 * <p> 3401 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 3402 * then the new matrix will be <code>M * L</code>. So when transforming a 3403 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 3404 * the lookat transformation will be applied first! 3405 * <p> 3406 * In order to set the matrix to a rotation transformation without post-multiplying it, 3407 * use {@link #rotationTowards(double, double, double, double, double, double) rotationTowards()}. 3408 * <p> 3409 * This method is equivalent to calling: <code>mul(new Matrix3d().lookAlong(-dirX, -dirY, -dirZ, upX, upY, upZ).invert(), dest)</code> 3410 * 3411 * @see #rotateTowards(Vector3d, Vector3d) 3412 * @see #rotationTowards(double, double, double, double, double, double) 3413 * 3414 * @param dirX 3415 * the x-coordinate of the direction to rotate towards 3416 * @param dirY 3417 * the y-coordinate of the direction to rotate towards 3418 * @param dirZ 3419 * the z-coordinate of the direction to rotate towards 3420 * @param upX 3421 * the x-coordinate of the up vector 3422 * @param upY 3423 * the y-coordinate of the up vector 3424 * @param upZ 3425 * the z-coordinate of the up vector 3426 * @param dest 3427 * will hold the result 3428 * @return dest 3429 */ 3430 public Matrix3d rotateTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ, ref Matrix3d dest) { 3431 // Normalize direction 3432 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 3433 double ndirX = dirX * invDirLength; 3434 double ndirY = dirY * invDirLength; 3435 double ndirZ = dirZ * invDirLength; 3436 // left = up x direction 3437 double leftX, leftY, leftZ; 3438 leftX = upY * ndirZ - upZ * ndirY; 3439 leftY = upZ * ndirX - upX * ndirZ; 3440 leftZ = upX * ndirY - upY * ndirX; 3441 // normalize left 3442 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 3443 leftX *= invLeftLength; 3444 leftY *= invLeftLength; 3445 leftZ *= invLeftLength; 3446 // up = direction x left 3447 double upnX = ndirY * leftZ - ndirZ * leftY; 3448 double upnY = ndirZ * leftX - ndirX * leftZ; 3449 double upnZ = ndirX * leftY - ndirY * leftX; 3450 double rm00 = leftX; 3451 double rm01 = leftY; 3452 double rm02 = leftZ; 3453 double rm10 = upnX; 3454 double rm11 = upnY; 3455 double rm12 = upnZ; 3456 double rm20 = ndirX; 3457 double rm21 = ndirY; 3458 double rm22 = ndirZ; 3459 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 3460 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 3461 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 3462 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 3463 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 3464 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 3465 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 3466 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 3467 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 3468 dest.m00 = nm00; 3469 dest.m01 = nm01; 3470 dest.m02 = nm02; 3471 dest.m10 = nm10; 3472 dest.m11 = nm11; 3473 dest.m12 = nm12; 3474 return dest; 3475 } 3476 3477 /** 3478 * Set this matrix to a model transformation for a right-handed coordinate system, 3479 * that aligns the local <code>-z</code> axis with <code>center - eye</code>. 3480 * <p> 3481 * In order to apply the rotation transformation to a previous existing transformation, 3482 * use {@link #rotateTowards(double, double, double, double, double, double) rotateTowards}. 3483 * <p> 3484 * This method is equivalent to calling: <code>setLookAlong(new Vector3d(dir).negate(), up).invert()</code> 3485 * 3486 * @see #rotationTowards(Vector3d, Vector3d) 3487 * @see #rotateTowards(double, double, double, double, double, double) 3488 * 3489 * @param dir 3490 * the direction to orient the local -z axis towards 3491 * @param up 3492 * the up vector 3493 * @return this 3494 */ 3495 ref public Matrix3d rotationTowards(Vector3d dir, Vector3d up) return { 3496 return rotationTowards(dir.x, dir.y, dir.z, up.x, up.y, up.z); 3497 } 3498 3499 /** 3500 * Set this matrix to a model transformation for a right-handed coordinate system, 3501 * that aligns the local <code>-z</code> axis with <code>center - eye</code>. 3502 * <p> 3503 * In order to apply the rotation transformation to a previous existing transformation, 3504 * use {@link #rotateTowards(double, double, double, double, double, double) rotateTowards}. 3505 * <p> 3506 * This method is equivalent to calling: <code>setLookAlong(-dirX, -dirY, -dirZ, upX, upY, upZ).invert()</code> 3507 * 3508 * @see #rotateTowards(Vector3d, Vector3d) 3509 * @see #rotationTowards(double, double, double, double, double, double) 3510 * 3511 * @param dirX 3512 * the x-coordinate of the direction to rotate towards 3513 * @param dirY 3514 * the y-coordinate of the direction to rotate towards 3515 * @param dirZ 3516 * the z-coordinate of the direction to rotate towards 3517 * @param upX 3518 * the x-coordinate of the up vector 3519 * @param upY 3520 * the y-coordinate of the up vector 3521 * @param upZ 3522 * the z-coordinate of the up vector 3523 * @return this 3524 */ 3525 ref public Matrix3d rotationTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ) return { 3526 // Normalize direction 3527 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 3528 double ndirX = dirX * invDirLength; 3529 double ndirY = dirY * invDirLength; 3530 double ndirZ = dirZ * invDirLength; 3531 // left = up x direction 3532 double leftX, leftY, leftZ; 3533 leftX = upY * ndirZ - upZ * ndirY; 3534 leftY = upZ * ndirX - upX * ndirZ; 3535 leftZ = upX * ndirY - upY * ndirX; 3536 // normalize left 3537 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 3538 leftX *= invLeftLength; 3539 leftY *= invLeftLength; 3540 leftZ *= invLeftLength; 3541 // up = direction x left 3542 double upnX = ndirY * leftZ - ndirZ * leftY; 3543 double upnY = ndirZ * leftX - ndirX * leftZ; 3544 double upnZ = ndirX * leftY - ndirY * leftX; 3545 this.m00 = leftX; 3546 this.m01 = leftY; 3547 this.m02 = leftZ; 3548 this.m10 = upnX; 3549 this.m11 = upnY; 3550 this.m12 = upnZ; 3551 this.m20 = ndirX; 3552 this.m21 = ndirY; 3553 this.m22 = ndirZ; 3554 return this; 3555 } 3556 3557 public Vector3d getEulerAnglesZYX(ref Vector3d dest) { 3558 dest.x = Math.atan2(m12, m22); 3559 dest.y = Math.atan2(-m02, Math.sqrt(1.0 - m02 * m02)); 3560 dest.z = Math.atan2(m01, m00); 3561 return dest; 3562 } 3563 3564 public Vector3d getEulerAnglesXYZ(ref Vector3d dest) { 3565 dest.x = Math.atan2(-m21, m22); 3566 dest.y = Math.atan2(m20, Math.sqrt(1.0 - m20 * m20)); 3567 dest.z = Math.atan2(-m10, m00); 3568 return dest; 3569 } 3570 3571 /** 3572 * Apply an oblique projection transformation to this matrix with the given values for <code>a</code> and 3573 * <code>b</code>. 3574 * <p> 3575 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the oblique transformation matrix, 3576 * then the new matrix will be <code>M * O</code>. So when transforming a 3577 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 3578 * oblique transformation will be applied first! 3579 * <p> 3580 * The oblique transformation is defined as: 3581 * <pre> 3582 * x' = x + a*z 3583 * y' = y + a*z 3584 * z' = z 3585 * </pre> 3586 * or in matrix form: 3587 * <pre> 3588 * 1 0 a 3589 * 0 1 b 3590 * 0 0 1 3591 * </pre> 3592 * 3593 * @param a 3594 * the value for the z factor that applies to x 3595 * @param b 3596 * the value for the z factor that applies to y 3597 * @return this 3598 */ 3599 ref public Matrix3d obliqueZ(double a, double b) return { 3600 this.m20 = m00 * a + m10 * b + m20; 3601 this.m21 = m01 * a + m11 * b + m21; 3602 this.m22 = m02 * a + m12 * b + m22; 3603 return this; 3604 } 3605 3606 /** 3607 * Apply an oblique projection transformation to this matrix with the given values for <code>a</code> and 3608 * <code>b</code> and store the result in <code>dest</code>. 3609 * <p> 3610 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the oblique transformation matrix, 3611 * then the new matrix will be <code>M * O</code>. So when transforming a 3612 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 3613 * oblique transformation will be applied first! 3614 * <p> 3615 * The oblique transformation is defined as: 3616 * <pre> 3617 * x' = x + a*z 3618 * y' = y + a*z 3619 * z' = z 3620 * </pre> 3621 * or in matrix form: 3622 * <pre> 3623 * 1 0 a 3624 * 0 1 b 3625 * 0 0 1 3626 * </pre> 3627 * 3628 * @param a 3629 * the value for the z factor that applies to x 3630 * @param b 3631 * the value for the z factor that applies to y 3632 * @param dest 3633 * will hold the result 3634 * @return dest 3635 */ 3636 public Matrix3d obliqueZ(double a, double b, ref Matrix3d dest) { 3637 dest.m00 = m00; 3638 dest.m01 = m01; 3639 dest.m02 = m02; 3640 dest.m10 = m10; 3641 dest.m11 = m11; 3642 dest.m12 = m12; 3643 dest.m20 = m00 * a + m10 * b + m20; 3644 dest.m21 = m01 * a + m11 * b + m21; 3645 dest.m22 = m02 * a + m12 * b + m22; 3646 return dest; 3647 } 3648 3649 public Matrix3d reflect(double nx, double ny, double nz, ref Matrix3d dest) { 3650 double da = nx + nx, db = ny + ny, d = nz + nz; 3651 double rm00 = 1.0 - da * nx; 3652 double rm01 = -da * ny; 3653 double rm02 = -da * nz; 3654 double rm10 = -db * nx; 3655 double rm11 = 1.0 - db * ny; 3656 double rm12 = -db * nz; 3657 double rm20 = -d * nx; 3658 double rm21 = -d * ny; 3659 double rm22 = 1.0 - d * nz; 3660 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 3661 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 3662 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 3663 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 3664 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 3665 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 3666 return dest 3667 ._m20(m00 * rm20 + m10 * rm21 + m20 * rm22) 3668 ._m21(m01 * rm20 + m11 * rm21 + m21 * rm22) 3669 ._m22(m02 * rm20 + m12 * rm21 + m22 * rm22) 3670 ._m00(nm00) 3671 ._m01(nm01) 3672 ._m02(nm02) 3673 ._m10(nm10) 3674 ._m11(nm11) 3675 ._m12(nm12); 3676 } 3677 3678 /** 3679 * Apply a mirror/reflection transformation to this matrix that reflects through the given plane 3680 * specified via the plane normal. 3681 * <p> 3682 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the reflection matrix, 3683 * then the new matrix will be <code>M * R</code>. So when transforming a 3684 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3685 * reflection will be applied first! 3686 * 3687 * @param nx 3688 * the x-coordinate of the plane normal 3689 * @param ny 3690 * the y-coordinate of the plane normal 3691 * @param nz 3692 * the z-coordinate of the plane normal 3693 * @return this 3694 */ 3695 ref public Matrix3d reflect(double nx, double ny, double nz) return { 3696 reflect(nx, ny, nz, this); 3697 return this; 3698 } 3699 3700 /** 3701 * Apply a mirror/reflection transformation to this matrix that reflects through the given plane 3702 * specified via the plane normal. 3703 * <p> 3704 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the reflection matrix, 3705 * then the new matrix will be <code>M * R</code>. So when transforming a 3706 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3707 * reflection will be applied first! 3708 * 3709 * @param normal 3710 * the plane normal 3711 * @return this 3712 */ 3713 ref public Matrix3d reflect(Vector3d normal) return { 3714 return reflect(normal.x, normal.y, normal.z); 3715 } 3716 3717 /** 3718 * Apply a mirror/reflection transformation to this matrix that reflects about a plane 3719 * specified via the plane orientation. 3720 * <p> 3721 * This method can be used to build a reflection transformation based on the orientation of a mirror object in the scene. 3722 * It is assumed that the default mirror plane's normal is <code>(0, 0, 1)</code>. So, if the given {@link Quaterniond} is 3723 * the identity (does not apply any additional rotation), the reflection plane will be <code>z=0</code>. 3724 * <p> 3725 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the reflection matrix, 3726 * then the new matrix will be <code>M * R</code>. So when transforming a 3727 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3728 * reflection will be applied first! 3729 * 3730 * @param orientation 3731 * the plane orientation 3732 * @return this 3733 */ 3734 ref public Matrix3d reflect(Quaterniond orientation) return { 3735 reflect(orientation, this); 3736 return this; 3737 } 3738 3739 public Matrix3d reflect(Quaterniond orientation, ref Matrix3d dest) { 3740 double num1 = orientation.x + orientation.x; 3741 double num2 = orientation.y + orientation.y; 3742 double num3 = orientation.z + orientation.z; 3743 double normalX = cast(double) (orientation.x * num3 + orientation.w * num2); 3744 double normalY = cast(double) (orientation.y * num3 - orientation.w * num1); 3745 double normalZ = cast(double) (1.0 - (orientation.x * num1 + orientation.y * num2)); 3746 return reflect(normalX, normalY, normalZ, dest); 3747 } 3748 3749 public Matrix3d reflect(Vector3d normal, ref Matrix3d dest) { 3750 return reflect(normal.x, normal.y, normal.z, dest); 3751 } 3752 3753 /** 3754 * Set this matrix to a mirror/reflection transformation that reflects through the given plane 3755 * specified via the plane normal. 3756 * 3757 * @param nx 3758 * the x-coordinate of the plane normal 3759 * @param ny 3760 * the y-coordinate of the plane normal 3761 * @param nz 3762 * the z-coordinate of the plane normal 3763 * @return this 3764 */ 3765 ref public Matrix3d reflection(double nx, double ny, double nz) return { 3766 double da = nx + nx, db = ny + ny, d = nz + nz; 3767 this._m00(1.0 - da * nx); 3768 this._m01(-da * ny); 3769 this._m02(-da * nz); 3770 this._m10(-db * nx); 3771 this._m11(1.0 - db * ny); 3772 this._m12(-db * nz); 3773 this._m20(-d * nx); 3774 this._m21(-d * ny); 3775 this._m22(1.0 - d * nz); 3776 return this; 3777 } 3778 3779 /** 3780 * Set this matrix to a mirror/reflection transformation that reflects through the given plane 3781 * specified via the plane normal. 3782 * 3783 * @param normal 3784 * the plane normal 3785 * @return this 3786 */ 3787 ref public Matrix3d reflection(Vector3d normal) return { 3788 return reflection(normal.x, normal.y, normal.z); 3789 } 3790 3791 /** 3792 * Set this matrix to a mirror/reflection transformation that reflects through a plane 3793 * specified via the plane orientation. 3794 * <p> 3795 * This method can be used to build a reflection transformation based on the orientation of a mirror object in the scene. 3796 * It is assumed that the default mirror plane's normal is <code>(0, 0, 1)</code>. So, if the given {@link Quaterniond} is 3797 * the identity (does not apply any additional rotation), the reflection plane will be <code>z=0</code>, offset by the given <code>point</code>. 3798 * 3799 * @param orientation 3800 * the plane orientation 3801 * @return this 3802 */ 3803 ref public Matrix3d reflection(Quaterniond orientation) return { 3804 double num1 = orientation.x + orientation.x; 3805 double num2 = orientation.y + orientation.y; 3806 double num3 = orientation.z + orientation.z; 3807 double normalX = orientation.x * num3 + orientation.w * num2; 3808 double normalY = orientation.y * num3 - orientation.w * num1; 3809 double normalZ = 1.0 - (orientation.x * num1 + orientation.y * num2); 3810 return reflection(normalX, normalY, normalZ); 3811 } 3812 3813 public bool isFinite() { 3814 return Math.isFinite(m00) && Math.isFinite(m01) && Math.isFinite(m02) && 3815 Math.isFinite(m10) && Math.isFinite(m11) && Math.isFinite(m12) && 3816 Math.isFinite(m20) && Math.isFinite(m21) && Math.isFinite(m22); 3817 } 3818 3819 public double quadraticFormProduct(double x, double y, double z) { 3820 double Axx = m00 * x + m10 * y + m20 * z; 3821 double Axy = m01 * x + m11 * y + m21 * z; 3822 double Axz = m02 * x + m12 * y + m22 * z; 3823 return x * Axx + y * Axy + z * Axz; 3824 } 3825 3826 public double quadraticFormProduct(Vector3d v) { 3827 return quadraticFormProduct(v.x, v.y, v.z); 3828 } 3829 3830 /** 3831 * Multiply <code>this</code> by the matrix 3832 * <pre> 3833 * 1 0 0 3834 * 0 0 1 3835 * 0 1 0 3836 * </pre> 3837 * 3838 * @return this 3839 */ 3840 ref public Matrix3d mapXZy() return { 3841 mapXZY(this); 3842 return this; 3843 } 3844 public Matrix3d mapXZY(ref Matrix3d dest) { 3845 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 3846 return dest._m00(m00)._m01(m01)._m02(m02)._m10(m20)._m11(m21)._m12(m22)._m20(__m10)._m21(__m11)._m22(__m12); 3847 } 3848 /** 3849 * Multiply <code>this</code> by the matrix 3850 * <pre> 3851 * 1 0 0 3852 * 0 0 -1 3853 * 0 1 0 3854 * </pre> 3855 * 3856 * @return this 3857 */ 3858 ref public Matrix3d mapXZny() return { 3859 mapXZnY(this); 3860 return this; 3861 } 3862 public Matrix3d mapXZnY(ref Matrix3d dest) { 3863 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 3864 return dest._m00(m00)._m01(m01)._m02(m02)._m10(m20)._m11(m21)._m12(m22)._m20(-__m10)._m21(-__m11)._m22(-__m12); 3865 } 3866 /** 3867 * Multiply <code>this</code> by the matrix 3868 * <pre> 3869 * 1 0 0 3870 * 0 -1 0 3871 * 0 0 -1 3872 * </pre> 3873 * 3874 * @return this 3875 */ 3876 ref public Matrix3d mapXnYnz() return { 3877 mapXnYnZ(this); 3878 return this; 3879 } 3880 public Matrix3d mapXnYnZ(ref Matrix3d dest) { 3881 return dest._m00(m00)._m01(m01)._m02(m02)._m10(-m10)._m11(-m11)._m12(-m12)._m20(-m20)._m21(-m21)._m22(-m22); 3882 } 3883 /** 3884 * Multiply <code>this</code> by the matrix 3885 * <pre> 3886 * 1 0 0 3887 * 0 0 1 3888 * 0 -1 0 3889 * </pre> 3890 * 3891 * @return this 3892 */ 3893 ref public Matrix3d mapXnZy() return { 3894 mapXnZY(this); 3895 return this; 3896 } 3897 public Matrix3d mapXnZY(ref Matrix3d dest) { 3898 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 3899 return dest._m00(m00)._m01(m01)._m02(m02)._m10(-m20)._m11(-m21)._m12(-m22)._m20(__m10)._m21(__m11)._m22(__m12); 3900 } 3901 /** 3902 * Multiply <code>this</code> by the matrix 3903 * <pre> 3904 * 1 0 0 3905 * 0 0 -1 3906 * 0 -1 0 3907 * </pre> 3908 * 3909 * @return this 3910 */ 3911 ref public Matrix3d mapXnZny() return { 3912 mapXnZnY(this); 3913 return this; 3914 } 3915 public Matrix3d mapXnZnY(ref Matrix3d dest) { 3916 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 3917 return dest._m00(m00)._m01(m01)._m02(m02)._m10(-m20)._m11(-m21)._m12(-m22)._m20(-__m10)._m21(-__m11)._m22(-__m12); 3918 } 3919 /** 3920 * Multiply <code>this</code> by the matrix 3921 * <pre> 3922 * 0 1 0 3923 * 1 0 0 3924 * 0 0 1 3925 * </pre> 3926 * 3927 * @return this 3928 */ 3929 ref public Matrix3d mapYXz() return { 3930 mapYXZ(this); 3931 return this; 3932 } 3933 public Matrix3d mapYXZ(ref Matrix3d dest) { 3934 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 3935 return dest._m00(m10)._m01(m11)._m02(m12)._m10(__m00)._m11(__m01)._m12(__m02)._m20(m20)._m21(m21)._m22(m22); 3936 } 3937 /** 3938 * Multiply <code>this</code> by the matrix 3939 * <pre> 3940 * 0 1 0 3941 * 1 0 0 3942 * 0 0 -1 3943 * </pre> 3944 * 3945 * @return this 3946 */ 3947 ref public Matrix3d mapYXnz() return { 3948 mapYXnZ(this); 3949 return this; 3950 } 3951 public Matrix3d mapYXnZ(ref Matrix3d dest) { 3952 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 3953 return dest._m00(m10)._m01(m11)._m02(m12)._m10(__m00)._m11(__m01)._m12(__m02)._m20(-m20)._m21(-m21)._m22(-m22); 3954 } 3955 /** 3956 * Multiply <code>this</code> by the matrix 3957 * <pre> 3958 * 0 0 1 3959 * 1 0 0 3960 * 0 1 0 3961 * </pre> 3962 * 3963 * @return this 3964 */ 3965 ref public Matrix3d mapYZx() return { 3966 mapYZX(this); 3967 return this; 3968 } 3969 public Matrix3d mapYZX(ref Matrix3d dest) { 3970 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 3971 return dest._m00(m10)._m01(m11)._m02(m12)._m10(m20)._m11(m21)._m12(m22)._m20(__m00)._m21(__m01)._m22(__m02); 3972 } 3973 /** 3974 * Multiply <code>this</code> by the matrix 3975 * <pre> 3976 * 0 0 -1 3977 * 1 0 0 3978 * 0 1 0 3979 * </pre> 3980 * 3981 * @return this 3982 */ 3983 ref public Matrix3d mapYZnx() return { 3984 mapYZnX(this); 3985 return this; 3986 } 3987 public Matrix3d mapYZnX(ref Matrix3d dest) { 3988 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 3989 return dest._m00(m10)._m01(m11)._m02(m12)._m10(m20)._m11(m21)._m12(m22)._m20(-__m00)._m21(-__m01)._m22(-__m02); 3990 } 3991 /** 3992 * Multiply <code>this</code> by the matrix 3993 * <pre> 3994 * 0 -1 0 3995 * 1 0 0 3996 * 0 0 1 3997 * </pre> 3998 * 3999 * @return this 4000 */ 4001 ref public Matrix3d mapYnXz() return { 4002 mapYnXZ(this); 4003 return this; 4004 } 4005 public Matrix3d mapYnXZ(ref Matrix3d dest) { 4006 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4007 return dest._m00(m10)._m01(m11)._m02(m12)._m10(-__m00)._m11(-__m01)._m12(-__m02)._m20(m20)._m21(m21)._m22(m22); 4008 } 4009 /** 4010 * Multiply <code>this</code> by the matrix 4011 * <pre> 4012 * 0 -1 0 4013 * 1 0 0 4014 * 0 0 -1 4015 * </pre> 4016 * 4017 * @return this 4018 */ 4019 ref public Matrix3d mapYnXnz() return { 4020 mapYnXnZ(this); 4021 return this; 4022 } 4023 public Matrix3d mapYnXnZ(ref Matrix3d dest) { 4024 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4025 return dest._m00(m10)._m01(m11)._m02(m12)._m10(-__m00)._m11(-__m01)._m12(-__m02)._m20(-m20)._m21(-m21)._m22(-m22); 4026 } 4027 /** 4028 * Multiply <code>this</code> by the matrix 4029 * <pre> 4030 * 0 0 1 4031 * 1 0 0 4032 * 0 -1 0 4033 * </pre> 4034 * 4035 * @return this 4036 */ 4037 ref public Matrix3d mapYnZx() return { 4038 mapYnZX(this); 4039 return this; 4040 } 4041 public Matrix3d mapYnZX(ref Matrix3d dest) { 4042 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4043 return dest._m00(m10)._m01(m11)._m02(m12)._m10(-m20)._m11(-m21)._m12(-m22)._m20(__m00)._m21(__m01)._m22(__m02); 4044 } 4045 /** 4046 * Multiply <code>this</code> by the matrix 4047 * <pre> 4048 * 0 0 -1 4049 * 1 0 0 4050 * 0 -1 0 4051 * </pre> 4052 * 4053 * @return this 4054 */ 4055 ref public Matrix3d mapYnZnx() return { 4056 mapYnZnX(this); 4057 return this; 4058 } 4059 public Matrix3d mapYnZnX(ref Matrix3d dest) { 4060 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4061 return dest._m00(m10)._m01(m11)._m02(m12)._m10(-m20)._m11(-m21)._m12(-m22)._m20(-__m00)._m21(-__m01)._m22(-__m02); 4062 } 4063 /** 4064 * Multiply <code>this</code> by the matrix 4065 * <pre> 4066 * 0 1 0 4067 * 0 0 1 4068 * 1 0 0 4069 * </pre> 4070 * 4071 * @return this 4072 */ 4073 ref public Matrix3d mapZXy() return { 4074 mapZXY(this); 4075 return this; 4076 } 4077 public Matrix3d mapZXY(ref Matrix3d dest) { 4078 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4079 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 4080 return dest._m00(m20)._m01(m21)._m02(m22)._m10(__m00)._m11(__m01)._m12(__m02)._m20(__m10)._m21(__m11)._m22(__m12); 4081 } 4082 /** 4083 * Multiply <code>this</code> by the matrix 4084 * <pre> 4085 * 0 1 0 4086 * 0 0 -1 4087 * 1 0 0 4088 * </pre> 4089 * 4090 * @return this 4091 */ 4092 ref public Matrix3d mapZXny() return { 4093 mapZXnY(this); 4094 return this; 4095 } 4096 public Matrix3d mapZXnY(ref Matrix3d dest) { 4097 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4098 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 4099 return dest._m00(m20)._m01(m21)._m02(m22)._m10(__m00)._m11(__m01)._m12(__m02)._m20(-__m10)._m21(-__m11)._m22(-__m12); 4100 } 4101 /** 4102 * Multiply <code>this</code> by the matrix 4103 * <pre> 4104 * 0 0 1 4105 * 0 1 0 4106 * 1 0 0 4107 * </pre> 4108 * 4109 * @return this 4110 */ 4111 ref public Matrix3d mapZYx() return { 4112 mapZYX(this); 4113 return this; 4114 } 4115 public Matrix3d mapZYX(ref Matrix3d dest) { 4116 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4117 return dest._m00(m20)._m01(m21)._m02(m22)._m10(m10)._m11(m11)._m12(m12)._m20(__m00)._m21(__m01)._m22(__m02); 4118 } 4119 /** 4120 * Multiply <code>this</code> by the matrix 4121 * <pre> 4122 * 0 0 -1 4123 * 0 1 0 4124 * 1 0 0 4125 * </pre> 4126 * 4127 * @return this 4128 */ 4129 ref public Matrix3d mapZYnx() return { 4130 mapZYnX(this); 4131 return this; 4132 } 4133 public Matrix3d mapZYnX(ref Matrix3d dest) { 4134 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4135 return dest._m00(m20)._m01(m21)._m02(m22)._m10(m10)._m11(m11)._m12(m12)._m20(-__m00)._m21(-__m01)._m22(-__m02); 4136 } 4137 /** 4138 * Multiply <code>this</code> by the matrix 4139 * <pre> 4140 * 0 -1 0 4141 * 0 0 1 4142 * 1 0 0 4143 * </pre> 4144 * 4145 * @return this 4146 */ 4147 ref public Matrix3d mapZnXy() return { 4148 mapZnXY(this); 4149 return this; 4150 } 4151 public Matrix3d mapZnXY(ref Matrix3d dest) { 4152 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4153 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 4154 return dest._m00(m20)._m01(m21)._m02(m22)._m10(-__m00)._m11(-__m01)._m12(-__m02)._m20(__m10)._m21(__m11)._m22(__m12); 4155 } 4156 /** 4157 * Multiply <code>this</code> by the matrix 4158 * <pre> 4159 * 0 -1 0 4160 * 0 0 -1 4161 * 1 0 0 4162 * </pre> 4163 * 4164 * @return this 4165 */ 4166 ref public Matrix3d mapZnXny() return { 4167 mapZnXnY(this); 4168 return this; 4169 } 4170 public Matrix3d mapZnXnY(ref Matrix3d dest) { 4171 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4172 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 4173 return dest._m00(m20)._m01(m21)._m02(m22)._m10(-__m00)._m11(-__m01)._m12(-__m02)._m20(-__m10)._m21(-__m11)._m22(-__m12); 4174 } 4175 /** 4176 * Multiply <code>this</code> by the matrix 4177 * <pre> 4178 * 0 0 1 4179 * 0 -1 0 4180 * 1 0 0 4181 * </pre> 4182 * 4183 * @return this 4184 */ 4185 ref public Matrix3d mapZnYx() return { 4186 mapZnYX(this); 4187 return this; 4188 } 4189 public Matrix3d mapZnYX(ref Matrix3d dest) { 4190 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4191 return dest._m00(m20)._m01(m21)._m02(m22)._m10(-m10)._m11(-m11)._m12(-m12)._m20(__m00)._m21(__m01)._m22(__m02); 4192 } 4193 /** 4194 * Multiply <code>this</code> by the matrix 4195 * <pre> 4196 * 0 0 -1 4197 * 0 -1 0 4198 * 1 0 0 4199 * </pre> 4200 * 4201 * @return this 4202 */ 4203 ref public Matrix3d mapZnYnx() return { 4204 mapZnYnX(this); 4205 return this; 4206 } 4207 public Matrix3d mapZnYnX(ref Matrix3d dest) { 4208 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4209 return dest._m00(m20)._m01(m21)._m02(m22)._m10(-m10)._m11(-m11)._m12(-m12)._m20(-__m00)._m21(-__m01)._m22(-__m02); 4210 } 4211 /** 4212 * Multiply <code>this</code> by the matrix 4213 * <pre> 4214 * -1 0 0 4215 * 0 1 0 4216 * 0 0 -1 4217 * </pre> 4218 * 4219 * @return this 4220 */ 4221 ref public Matrix3d mapnXYnz() return { 4222 mapnXYnZ(this); 4223 return this; 4224 } 4225 public Matrix3d mapnXYnZ(ref Matrix3d dest) { 4226 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(m10)._m11(m11)._m12(m12)._m20(-m20)._m21(-m21)._m22(-m22); 4227 } 4228 /** 4229 * Multiply <code>this</code> by the matrix 4230 * <pre> 4231 * -1 0 0 4232 * 0 0 1 4233 * 0 1 0 4234 * </pre> 4235 * 4236 * @return this 4237 */ 4238 ref public Matrix3d mapnXZy() return { 4239 mapnXZY(this); 4240 return this; 4241 } 4242 public Matrix3d mapnXZY(ref Matrix3d dest) { 4243 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 4244 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(m20)._m11(m21)._m12(m22)._m20(__m10)._m21(__m11)._m22(__m12); 4245 } 4246 /** 4247 * Multiply <code>this</code> by the matrix 4248 * <pre> 4249 * -1 0 0 4250 * 0 0 -1 4251 * 0 1 0 4252 * </pre> 4253 * 4254 * @return this 4255 */ 4256 ref public Matrix3d mapnXZny() return { 4257 mapnXZnY(this); 4258 return this; 4259 } 4260 public Matrix3d mapnXZnY(ref Matrix3d dest) { 4261 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 4262 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(m20)._m11(m21)._m12(m22)._m20(-__m10)._m21(-__m11)._m22(-__m12); 4263 } 4264 /** 4265 * Multiply <code>this</code> by the matrix 4266 * <pre> 4267 * -1 0 0 4268 * 0 -1 0 4269 * 0 0 1 4270 * </pre> 4271 * 4272 * @return this 4273 */ 4274 ref public Matrix3d mapnXnYz() return { 4275 mapnXnYZ(this); 4276 return this; 4277 } 4278 public Matrix3d mapnXnYZ(ref Matrix3d dest) { 4279 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(-m10)._m11(-m11)._m12(-m12)._m20(m20)._m21(m21)._m22(m22); 4280 } 4281 /** 4282 * Multiply <code>this</code> by the matrix 4283 * <pre> 4284 * -1 0 0 4285 * 0 -1 0 4286 * 0 0 -1 4287 * </pre> 4288 * 4289 * @return this 4290 */ 4291 ref public Matrix3d mapnXnYnz() return { 4292 mapnXnYnZ(this); 4293 return this; 4294 } 4295 public Matrix3d mapnXnYnZ(ref Matrix3d dest) { 4296 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(-m10)._m11(-m11)._m12(-m12)._m20(-m20)._m21(-m21)._m22(-m22); 4297 } 4298 /** 4299 * Multiply <code>this</code> by the matrix 4300 * <pre> 4301 * -1 0 0 4302 * 0 0 1 4303 * 0 -1 0 4304 * </pre> 4305 * 4306 * @return this 4307 */ 4308 ref public Matrix3d mapnXnZy() return { 4309 mapnXnZY(this); 4310 return this; 4311 } 4312 public Matrix3d mapnXnZY(ref Matrix3d dest) { 4313 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 4314 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(-m20)._m11(-m21)._m12(-m22)._m20(__m10)._m21(__m11)._m22(__m12); 4315 } 4316 /** 4317 * Multiply <code>this</code> by the matrix 4318 * <pre> 4319 * -1 0 0 4320 * 0 0 -1 4321 * 0 -1 0 4322 * </pre> 4323 * 4324 * @return this 4325 */ 4326 ref public Matrix3d mapnXnZny() return { 4327 mapnXnZnY(this); 4328 return this; 4329 } 4330 public Matrix3d mapnXnZnY(ref Matrix3d dest) { 4331 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 4332 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(-m20)._m11(-m21)._m12(-m22)._m20(-__m10)._m21(-__m11)._m22(-__m12); 4333 } 4334 /** 4335 * Multiply <code>this</code> by the matrix 4336 * <pre> 4337 * 0 1 0 4338 * -1 0 0 4339 * 0 0 1 4340 * </pre> 4341 * 4342 * @return this 4343 */ 4344 ref public Matrix3d mapnYXz() return { 4345 mapnYXZ(this); 4346 return this; 4347 } 4348 public Matrix3d mapnYXZ(ref Matrix3d dest) { 4349 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4350 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(__m00)._m11(__m01)._m12(__m02)._m20(m20)._m21(m21)._m22(m22); 4351 } 4352 /** 4353 * Multiply <code>this</code> by the matrix 4354 * <pre> 4355 * 0 1 0 4356 * -1 0 0 4357 * 0 0 -1 4358 * </pre> 4359 * 4360 * @return this 4361 */ 4362 ref public Matrix3d mapnYXnz() return { 4363 mapnYXnZ(this); 4364 return this; 4365 } 4366 public Matrix3d mapnYXnZ(ref Matrix3d dest) { 4367 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4368 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(__m00)._m11(__m01)._m12(__m02)._m20(-m20)._m21(-m21)._m22(-m22); 4369 } 4370 /** 4371 * Multiply <code>this</code> by the matrix 4372 * <pre> 4373 * 0 0 1 4374 * -1 0 0 4375 * 0 1 0 4376 * </pre> 4377 * 4378 * @return this 4379 */ 4380 ref public Matrix3d mapnYZx() return { 4381 mapnYZX(this); 4382 return this; 4383 } 4384 public Matrix3d mapnYZX(ref Matrix3d dest) { 4385 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4386 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(m20)._m11(m21)._m12(m22)._m20(__m00)._m21(__m01)._m22(__m02); 4387 } 4388 /** 4389 * Multiply <code>this</code> by the matrix 4390 * <pre> 4391 * 0 0 -1 4392 * -1 0 0 4393 * 0 1 0 4394 * </pre> 4395 * 4396 * @return this 4397 */ 4398 ref public Matrix3d mapnYZnx() return { 4399 mapnYZnX(this); 4400 return this; 4401 } 4402 public Matrix3d mapnYZnX(ref Matrix3d dest) { 4403 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4404 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(m20)._m11(m21)._m12(m22)._m20(-__m00)._m21(-__m01)._m22(-__m02); 4405 } 4406 /** 4407 * Multiply <code>this</code> by the matrix 4408 * <pre> 4409 * 0 -1 0 4410 * -1 0 0 4411 * 0 0 1 4412 * </pre> 4413 * 4414 * @return this 4415 */ 4416 ref public Matrix3d mapnYnXz() return { 4417 mapnYnXZ(this); 4418 return this; 4419 } 4420 public Matrix3d mapnYnXZ(ref Matrix3d dest) { 4421 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4422 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(-__m00)._m11(-__m01)._m12(-__m02)._m20(m20)._m21(m21)._m22(m22); 4423 } 4424 /** 4425 * Multiply <code>this</code> by the matrix 4426 * <pre> 4427 * 0 -1 0 4428 * -1 0 0 4429 * 0 0 -1 4430 * </pre> 4431 * 4432 * @return this 4433 */ 4434 ref public Matrix3d mapnYnXnz() return { 4435 mapnYnXnZ(this); 4436 return this; 4437 } 4438 public Matrix3d mapnYnXnZ(ref Matrix3d dest) { 4439 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4440 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(-__m00)._m11(-__m01)._m12(-__m02)._m20(-m20)._m21(-m21)._m22(-m22); 4441 } 4442 /** 4443 * Multiply <code>this</code> by the matrix 4444 * <pre> 4445 * 0 0 1 4446 * -1 0 0 4447 * 0 -1 0 4448 * </pre> 4449 * 4450 * @return this 4451 */ 4452 ref public Matrix3d mapnYnZx() return { 4453 mapnYnZX(this); 4454 return this; 4455 } 4456 public Matrix3d mapnYnZX(ref Matrix3d dest) { 4457 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4458 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(-m20)._m11(-m21)._m12(-m22)._m20(__m00)._m21(__m01)._m22(__m02); 4459 } 4460 /** 4461 * Multiply <code>this</code> by the matrix 4462 * <pre> 4463 * 0 0 -1 4464 * -1 0 0 4465 * 0 -1 0 4466 * </pre> 4467 * 4468 * @return this 4469 */ 4470 ref public Matrix3d mapnYnZnx() return { 4471 mapnYnZnX(this); 4472 return this; 4473 } 4474 public Matrix3d mapnYnZnX(ref Matrix3d dest) { 4475 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4476 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(-m20)._m11(-m21)._m12(-m22)._m20(-__m00)._m21(-__m01)._m22(-__m02); 4477 } 4478 /** 4479 * Multiply <code>this</code> by the matrix 4480 * <pre> 4481 * 0 1 0 4482 * 0 0 1 4483 * -1 0 0 4484 * </pre> 4485 * 4486 * @return this 4487 */ 4488 ref public Matrix3d mapnZXy() return { 4489 mapnZXY(this); 4490 return this; 4491 } 4492 public Matrix3d mapnZXY(ref Matrix3d dest) { 4493 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4494 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 4495 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(__m00)._m11(__m01)._m12(__m02)._m20(__m10)._m21(__m11)._m22(__m12); 4496 } 4497 /** 4498 * Multiply <code>this</code> by the matrix 4499 * <pre> 4500 * 0 1 0 4501 * 0 0 -1 4502 * -1 0 0 4503 * </pre> 4504 * 4505 * @return this 4506 */ 4507 ref public Matrix3d mapnZXny() return { 4508 mapnZXnY(this); 4509 return this; 4510 } 4511 public Matrix3d mapnZXnY(ref Matrix3d dest) { 4512 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4513 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 4514 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(__m00)._m11(__m01)._m12(__m02)._m20(-__m10)._m21(-__m11)._m22(-__m12); 4515 } 4516 /** 4517 * Multiply <code>this</code> by the matrix 4518 * <pre> 4519 * 0 0 1 4520 * 0 1 0 4521 * -1 0 0 4522 * </pre> 4523 * 4524 * @return this 4525 */ 4526 ref public Matrix3d mapnZYx() return { 4527 mapnZYX(this); 4528 return this; 4529 } 4530 public Matrix3d mapnZYX(ref Matrix3d dest) { 4531 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4532 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(m10)._m11(m11)._m12(m12)._m20(__m00)._m21(__m01)._m22(__m02); 4533 } 4534 /** 4535 * Multiply <code>this</code> by the matrix 4536 * <pre> 4537 * 0 0 -1 4538 * 0 1 0 4539 * -1 0 0 4540 * </pre> 4541 * 4542 * @return this 4543 */ 4544 ref public Matrix3d mapnZYnx() return { 4545 mapnZYnX(this); 4546 return this; 4547 } 4548 public Matrix3d mapnZYnX(ref Matrix3d dest) { 4549 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4550 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(m10)._m11(m11)._m12(m12)._m20(-__m00)._m21(-__m01)._m22(-__m02); 4551 } 4552 /** 4553 * Multiply <code>this</code> by the matrix 4554 * <pre> 4555 * 0 -1 0 4556 * 0 0 1 4557 * -1 0 0 4558 * </pre> 4559 * 4560 * @return this 4561 */ 4562 ref public Matrix3d mapnZnXy() return { 4563 mapnZnXY(this); 4564 return this; 4565 } 4566 public Matrix3d mapnZnXY(ref Matrix3d dest) { 4567 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4568 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 4569 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(-__m00)._m11(-__m01)._m12(-__m02)._m20(__m10)._m21(__m11)._m22(__m12); 4570 } 4571 /** 4572 * Multiply <code>this</code> by the matrix 4573 * <pre> 4574 * 0 -1 0 4575 * 0 0 -1 4576 * -1 0 0 4577 * </pre> 4578 * 4579 * @return this 4580 */ 4581 ref public Matrix3d mapnZnXny() return { 4582 mapnZnXnY(this); 4583 return this; 4584 } 4585 public Matrix3d mapnZnXnY(ref Matrix3d dest) { 4586 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4587 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 4588 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(-__m00)._m11(-__m01)._m12(-__m02)._m20(-__m10)._m21(-__m11)._m22(-__m12); 4589 } 4590 /** 4591 * Multiply <code>this</code> by the matrix 4592 * <pre> 4593 * 0 0 1 4594 * 0 -1 0 4595 * -1 0 0 4596 * </pre> 4597 * 4598 * @return this 4599 */ 4600 ref public Matrix3d mapnZnYx() return { 4601 mapnZnYX(this); 4602 return this; 4603 } 4604 public Matrix3d mapnZnYX(ref Matrix3d dest) { 4605 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4606 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(-m10)._m11(-m11)._m12(-m12)._m20(__m00)._m21(__m01)._m22(__m02); 4607 } 4608 /** 4609 * Multiply <code>this</code> by the matrix 4610 * <pre> 4611 * 0 0 -1 4612 * 0 -1 0 4613 * -1 0 0 4614 * </pre> 4615 * 4616 * @return this 4617 */ 4618 ref public Matrix3d mapnZnYnx() return { 4619 mapnZnYnX(this); 4620 return this; 4621 } 4622 public Matrix3d mapnZnYnX(ref Matrix3d dest) { 4623 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 4624 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(-m10)._m11(-m11)._m12(-m12)._m20(-__m00)._m21(-__m01)._m22(-__m02); 4625 } 4626 4627 /** 4628 * Multiply <code>this</code> by the matrix 4629 * <pre> 4630 * -1 0 0 4631 * 0 1 0 4632 * 0 0 1 4633 * </pre> 4634 * 4635 * @return this 4636 */ 4637 ref public Matrix3d negatex() return { 4638 return _m00(-m00)._m01(-m01)._m02(-m02); 4639 } 4640 public Matrix3d negateX(ref Matrix3d dest) { 4641 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(m10)._m11(m11)._m12(m12)._m20(m20)._m21(m21)._m22(m22); 4642 } 4643 4644 /** 4645 * Multiply <code>this</code> by the matrix 4646 * <pre> 4647 * 1 0 0 4648 * 0 -1 0 4649 * 0 0 1 4650 * </pre> 4651 * 4652 * @return this 4653 */ 4654 ref public Matrix3d negatey() return { 4655 return _m10(-m10)._m11(-m11)._m12(-m12); 4656 } 4657 public Matrix3d negateY(ref Matrix3d dest) { 4658 return dest._m00(m00)._m01(m01)._m02(m02)._m10(-m10)._m11(-m11)._m12(-m12)._m20(m20)._m21(m21)._m22(m22); 4659 } 4660 4661 /** 4662 * Multiply <code>this</code> by the matrix 4663 * <pre> 4664 * 1 0 0 4665 * 0 1 0 4666 * 0 0 -1 4667 * </pre> 4668 * 4669 * @return this 4670 */ 4671 ref public Matrix3d negatez() return { 4672 return _m20(-m20)._m21(-m21)._m22(-m22); 4673 } 4674 public Matrix3d negateZ(ref Matrix3d dest) { 4675 return dest._m00(m00)._m01(m01)._m02(m02)._m10(m10)._m11(m11)._m12(m12)._m20(-m20)._m21(-m21)._m22(-m22); 4676 } 4677 }