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