1 /** 2 * Contains the definition of a Vector comprising 3 doubles and associated 3 * transformations. 4 * 5 * @author Richard Greenlees 6 * @author Kai Burjack 7 * @author F. Neurath 8 */ 9 module doml.vector_3d; 10 11 import Math = doml.math; 12 13 import doml.vector_2i; 14 import doml.vector_2d; 15 import doml.vector_3i; 16 import doml.vector_3d; 17 18 import doml.matrix_4d; 19 import doml.matrix_3d; 20 import doml.matrix_3x2d; 21 import doml.matrix_4x3d; 22 23 import doml.axis_angle_4d; 24 import doml.quaternion_d; 25 /* 26 * The MIT License 27 * 28 * Copyright (c) 2015-2021 Richard Greenlees 29 @#$%# Translated by jordan4ibanez 30 * 31 * Permission is hereby granted, free of charge, to any person obtaining a copy 32 * of this software and associated documentation files (the "Software"), to deal 33 * in the Software without restriction, including without limitation the rights 34 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 35 * copies of the Software, and to permit persons to whom the Software is 36 * furnished to do so, subject to the following conditions: 37 * 38 * The above copyright notice and this permission notice shall be included in 39 * all copies or substantial portions of the Software. 40 * 41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 46 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 47 * THE SOFTWARE. 48 */ 49 50 /** 51 * Contains the definition of a Vector comprising 3 doubles and associated 52 * transformations. 53 * 54 * @author Richard Greenlees 55 * @author Kai Burjack 56 * @author F. Neurath 57 */ 58 struct Vector3d { 59 60 /** 61 * The x component of the vector. 62 */ 63 public double x = 0.0; 64 /** 65 * The y component of the vector. 66 */ 67 public double y = 0.0; 68 /** 69 * The z component of the vector. 70 */ 71 public double z = 0.0; 72 73 /** 74 * Create a new {@link Vector3d} and initialize all three components with the given value. 75 * 76 * @param d 77 * the value of all three components 78 */ 79 this(double d) { 80 this.x = d; 81 this.y = d; 82 this.z = d; 83 } 84 85 /** 86 * Create a new {@link Vector3d} with the given component values. 87 * 88 * @param x 89 * the value of x 90 * @param y 91 * the value of y 92 * @param z 93 * the value of z 94 */ 95 this(double x, double y, double z) { 96 this.x = x; 97 this.y = y; 98 this.z = z; 99 } 100 101 102 /** 103 * Create a new {@link Vector3d} whose values will be copied from the given vector. 104 * 105 * @param v 106 * provides the initial values for the new vector 107 */ 108 this(Vector3i v) { 109 this.x = v.x; 110 this.y = v.y; 111 this.z = v.z; 112 } 113 114 /** 115 * Create a new {@link Vector3d} with the first two components from the 116 * given <code>v</code> and the given <code>z</code> 117 * 118 * @param v 119 * the {@link Vector2i} to copy the values from 120 * @param z 121 * the z component 122 */ 123 this(Vector2i v, double z) { 124 this.x = v.x; 125 this.y = v.y; 126 this.z = z; 127 } 128 129 /** 130 * Create a new {@link Vector3d} whose values will be copied from the given vector. 131 * 132 * @param v 133 * provides the initial values for the new vector 134 */ 135 this(Vector3d v) { 136 this.x = v.x; 137 this.y = v.y; 138 this.z = v.z; 139 } 140 141 /** 142 * Create a new {@link Vector3d} with the first two components from the 143 * given <code>v</code> and the given <code>z</code> 144 * 145 * @param v 146 * the {@link Vector2d} to copy the values from 147 * @param z 148 * the z component 149 */ 150 this(Vector2d v, double z) { 151 this.x = v.x; 152 this.y = v.y; 153 this.z = z; 154 } 155 156 /** 157 * Create a new {@link Vector3d} and initialize its three components from the first 158 * three elements of the given array. 159 * 160 * @param xyz 161 * the array containing at least three elements 162 */ 163 this(double[] xyz) { 164 this.x = xyz[0]; 165 this.y = xyz[1]; 166 this.z = xyz[2]; 167 } 168 169 170 /** 171 * Set the x, y and z components to match the supplied vector. 172 * 173 * @param v 174 * the vector to set this vector's components from 175 * @return this 176 */ 177 ref public Vector3d set(Vector3d v) return { 178 this.x = v.x; 179 this.y = v.y; 180 this.z = v.z; 181 return this; 182 } 183 184 /** 185 * Set the x, y and z components to match the supplied vector. 186 * 187 * @param v 188 * the vector to set this vector's components from 189 * @return this 190 */ 191 ref public Vector3d set(Vector3i v) return { 192 this.x = v.x; 193 this.y = v.y; 194 this.z = v.z; 195 return this; 196 } 197 198 /** 199 * Set the first two components from the given <code>v</code> 200 * and the z component from the given <code>z</code> 201 * 202 * @param v 203 * the {@link Vector2d} to copy the values from 204 * @param z 205 * the z component 206 * @return this 207 */ 208 ref public Vector3d set(Vector2d v, double z) return { 209 this.x = v.x; 210 this.y = v.y; 211 this.z = z; 212 return this; 213 } 214 215 /** 216 * Set the first two components from the given <code>v</code> 217 * and the z component from the given <code>z</code> 218 * 219 * @param v 220 * the {@link Vector2i} to copy the values from 221 * @param z 222 * the z component 223 * @return this 224 */ 225 ref public Vector3d set(Vector2i v, double z) return { 226 this.x = v.x; 227 this.y = v.y; 228 this.z = z; 229 return this; 230 } 231 232 /** 233 * Set the x, y, and z components to the supplied value. 234 * 235 * @param d 236 * the value of all three components 237 * @return this 238 */ 239 ref public Vector3d set(double d) return { 240 this.x = d; 241 this.y = d; 242 this.z = d; 243 return this; 244 } 245 246 /** 247 * Set the x, y and z components to the supplied values. 248 * 249 * @param x 250 * the x component 251 * @param y 252 * the y component 253 * @param z 254 * the z component 255 * @return this 256 */ 257 ref public Vector3d set(double x, double y, double z) return { 258 this.x = x; 259 this.y = y; 260 this.z = z; 261 return this; 262 } 263 264 /** 265 * Set the three components of this vector to the first three elements of the given array. 266 * 267 * @param xyz 268 * the array containing at least three elements 269 * @return this 270 */ 271 ref public Vector3d set(double[] xyz) return { 272 this.x = xyz[0]; 273 this.y = xyz[1]; 274 this.z = xyz[2]; 275 return this; 276 } 277 278 /** 279 * Set the value of the specified component of this vector. 280 * 281 * @param component 282 * the component whose value to set, within <code>[0..2]</code> 283 * @param value 284 * the value to set 285 * @return this 286 * @throws IllegalArgumentException if <code>component</code> is not within <code>[0..2]</code> 287 */ 288 ref public Vector3d setComponent(int component, double value) return { 289 switch (component) { 290 case 0: 291 x = value; 292 break; 293 case 1: 294 y = value; 295 break; 296 case 2: 297 z = value; 298 break; 299 default: {} 300 } 301 return this; 302 } 303 304 /** 305 * Subtract the supplied vector from this one. 306 * 307 * @param v 308 * the vector to subtract from this 309 * @return this 310 */ 311 ref public Vector3d sub(Vector3d v) return { 312 this.x = x - v.x; 313 this.y = y - v.y; 314 this.z = z - v.z; 315 return this; 316 } 317 318 public Vector3d sub(Vector3d v, ref Vector3d dest) { 319 dest.x = x - v.x; 320 dest.y = y - v.y; 321 dest.z = z - v.z; 322 return dest; 323 } 324 325 326 /** 327 * Subtract <code>(x, y, z)</code> from this vector. 328 * 329 * @param x 330 * the x component to subtract 331 * @param y 332 * the y component to subtract 333 * @param z 334 * the z component to subtract 335 * @return this 336 */ 337 ref public Vector3d sub(double x, double y, double z) return { 338 this.x = this.x - x; 339 this.y = this.y - y; 340 this.z = this.z - z; 341 return this; 342 } 343 344 public Vector3d sub(double x, double y, double z, ref Vector3d dest) { 345 dest.x = this.x - x; 346 dest.y = this.y - y; 347 dest.z = this.z - z; 348 return dest; 349 } 350 351 /** 352 * Add the supplied vector to this one. 353 * 354 * @param v 355 * the vector to add 356 * @return this 357 */ 358 ref public Vector3d add(Vector3d v) return { 359 this.x = x + v.x; 360 this.y = y + v.y; 361 this.z = z + v.z; 362 return this; 363 } 364 365 public Vector3d add(Vector3d v, ref Vector3d dest) { 366 dest.x = x + v.x; 367 dest.y = y + v.y; 368 dest.z = z + v.z; 369 return dest; 370 } 371 372 373 /** 374 * Increment the components of this vector by the given values. 375 * 376 * @param x 377 * the x component to add 378 * @param y 379 * the y component to add 380 * @param z 381 * the z component to add 382 * @return this 383 */ 384 ref public Vector3d add(double x, double y, double z) return { 385 this.x = this.x + x; 386 this.y = this.y + y; 387 this.z = this.z + z; 388 return this; 389 } 390 391 public Vector3d add(double x, double y, double z, ref Vector3d dest) { 392 dest.x = this.x + x; 393 dest.y = this.y + y; 394 dest.z = this.z + z; 395 return dest; 396 } 397 398 /** 399 * Add the component-wise multiplication of <code>a * b</code> to this vector. 400 * 401 * @param a 402 * the first multiplicand 403 * @param b 404 * the second multiplicand 405 * @return this 406 */ 407 ref public Vector3d fma(Vector3d a, Vector3d b) return { 408 this.x = Math.fma(a.x, b.x, x); 409 this.y = Math.fma(a.y, b.y, y); 410 this.z = Math.fma(a.z, b.z, z); 411 return this; 412 } 413 414 /** 415 * Add the component-wise multiplication of <code>a * b</code> to this vector. 416 * 417 * @param a 418 * the first multiplicand 419 * @param b 420 * the second multiplicand 421 * @return this 422 */ 423 ref public Vector3d fma(double a, Vector3d b) return { 424 this.x = Math.fma(a, b.x, x); 425 this.y = Math.fma(a, b.y, y); 426 this.z = Math.fma(a, b.z, z); 427 return this; 428 } 429 430 public Vector3d fma(Vector3d a, Vector3d b, ref Vector3d dest) { 431 dest.x = Math.fma(a.x, b.x, x); 432 dest.y = Math.fma(a.y, b.y, y); 433 dest.z = Math.fma(a.z, b.z, z); 434 return dest; 435 } 436 437 public Vector3d fma(double a, Vector3d b, ref Vector3d dest) { 438 dest.x = Math.fma(a, b.x, x); 439 dest.y = Math.fma(a, b.y, y); 440 dest.z = Math.fma(a, b.z, z); 441 return dest; 442 } 443 444 /** 445 * Add the component-wise multiplication of <code>this * a</code> to <code>b</code> 446 * and store the result in <code>this</code>. 447 * 448 * @param a 449 * the multiplicand 450 * @param b 451 * the addend 452 * @return this 453 */ 454 ref public Vector3d mulAdd(Vector3d a, Vector3d b) return { 455 this.x = Math.fma(x, a.x, b.x); 456 this.y = Math.fma(y, a.y, b.y); 457 this.z = Math.fma(z, a.z, b.z); 458 return this; 459 } 460 461 /** 462 * Add the component-wise multiplication of <code>this * a</code> to <code>b</code> 463 * and store the result in <code>this</code>. 464 * 465 * @param a 466 * the multiplicand 467 * @param b 468 * the addend 469 * @return this 470 */ 471 ref public Vector3d mulAdd(double a, Vector3d b) return { 472 this.x = Math.fma(x, a, b.x); 473 this.y = Math.fma(y, a, b.y); 474 this.z = Math.fma(z, a, b.z); 475 return this; 476 } 477 478 public Vector3d mulAdd(Vector3d a, Vector3d b, ref Vector3d dest) { 479 dest.x = Math.fma(x, a.x, b.x); 480 dest.y = Math.fma(y, a.y, b.y); 481 dest.z = Math.fma(z, a.z, b.z); 482 return dest; 483 } 484 485 public Vector3d mulAdd(double a, Vector3d b, ref Vector3d dest) { 486 dest.x = Math.fma(x, a, b.x); 487 dest.y = Math.fma(y, a, b.y); 488 dest.z = Math.fma(z, a, b.z); 489 return dest; 490 } 491 492 /** 493 * Multiply this Vector3d component-wise by another Vector3d. 494 * 495 * @param v 496 * the vector to multiply by 497 * @return this 498 */ 499 ref public Vector3d mul(Vector3d v) return { 500 this.x = x * v.x; 501 this.y = y * v.y; 502 this.z = z * v.z; 503 return this; 504 } 505 506 public Vector3d mul(Vector3d v, ref Vector3d dest) { 507 dest.x = x * v.x; 508 dest.y = y * v.y; 509 dest.z = z * v.z; 510 return dest; 511 } 512 513 /** 514 * Divide this Vector3d component-wise by another Vector3d. 515 * 516 * @param v 517 * the vector to divide by 518 * @return this 519 */ 520 ref public Vector3d div(Vector3d v) return { 521 this.x = x / v.x; 522 this.y = y / v.y; 523 this.z = z / v.z; 524 return this; 525 } 526 527 528 public Vector3d div(Vector3d v, ref Vector3d dest) { 529 dest.x = x / v.x; 530 dest.y = y / v.y; 531 dest.z = z / v.z; 532 return dest; 533 } 534 535 public Vector3d mulProject(Matrix4d mat, double w, ref Vector3d dest) { 536 double invW = 1.0 / Math.fma(mat.m03, x, Math.fma(mat.m13, y, Math.fma(mat.m23, z, mat.m33 * w))); 537 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30 * w))) * invW; 538 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31 * w))) * invW; 539 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32 * w))) * invW; 540 dest.x = rx; 541 dest.y = ry; 542 dest.z = rz; 543 return dest; 544 } 545 546 public Vector3d mulProject(Matrix4d mat, ref Vector3d dest) { 547 double invW = 1.0 / Math.fma(mat.m03, x, Math.fma(mat.m13, y, Math.fma(mat.m23, z, mat.m33))); 548 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30))) * invW; 549 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31))) * invW; 550 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32))) * invW; 551 dest.x = rx; 552 dest.y = ry; 553 dest.z = rz; 554 return dest; 555 } 556 557 /** 558 * Multiply the given matrix <code>mat</code> this Vector3d, perform perspective division. 559 * <p> 560 * This method uses <code>w=1.0</code> as the fourth vector component. 561 * 562 * @param mat 563 * the matrix to multiply this vector by 564 * @return this 565 */ 566 ref public Vector3d mulProject(Matrix4d mat) return { 567 double invW = 1.0 / Math.fma(mat.m03, x, Math.fma(mat.m13, y, Math.fma(mat.m23, z, mat.m33))); 568 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30))) * invW; 569 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31))) * invW; 570 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32))) * invW; 571 this.x = rx; 572 this.y = ry; 573 this.z = rz; 574 return this; 575 } 576 577 578 /** 579 * Multiply the given matrix <code>mat</code> with this Vector3d. 580 * 581 * @param mat 582 * the matrix to multiply this vector by 583 * @return this 584 */ 585 ref public Vector3d mul(Matrix3d mat) return { 586 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z)); 587 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z)); 588 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, mat.m22 * z)); 589 this.x = rx; 590 this.y = ry; 591 this.z = rz; 592 return this; 593 } 594 595 public Vector3d mul(Matrix3d mat, ref Vector3d dest) { 596 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z)); 597 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z)); 598 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, mat.m22 * z)); 599 dest.x = rx; 600 dest.y = ry; 601 dest.z = rz; 602 return dest; 603 } 604 605 /** 606 * Multiply the given matrix with this Vector3d by assuming a third row in the matrix of <code>(0, 0, 1)</code> 607 * and store the result in <code>this</code>. 608 * 609 * @param mat 610 * the matrix 611 * @return this 612 */ 613 ref public Vector3d mul(Matrix3x2d mat) return { 614 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z)); 615 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z)); 616 this.x = rx; 617 this.y = ry; 618 return this; 619 } 620 621 public Vector3d mul(Matrix3x2d mat, ref Vector3d dest) { 622 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z)); 623 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z)); 624 dest.x = rx; 625 dest.y = ry; 626 dest.z = z; 627 return dest; 628 } 629 630 631 /** 632 * Multiply the transpose of the given matrix with this Vector3d and store the result in <code>this</code>. 633 * 634 * @param mat 635 * the matrix 636 * @return this 637 */ 638 ref public Vector3d mulTranspose(Matrix3d mat) return { 639 double rx = Math.fma(mat.m00, x, Math.fma(mat.m01, y, mat.m02 * z)); 640 double ry = Math.fma(mat.m10, x, Math.fma(mat.m11, y, mat.m12 * z)); 641 double rz = Math.fma(mat.m20, x, Math.fma(mat.m21, y, mat.m22 * z)); 642 this.x = rx; 643 this.y = ry; 644 this.z = rz; 645 return this; 646 } 647 648 public Vector3d mulTranspose(Matrix3d mat, ref Vector3d dest) { 649 double rx = Math.fma(mat.m00, x, Math.fma(mat.m01, y, mat.m02 * z)); 650 double ry = Math.fma(mat.m10, x, Math.fma(mat.m11, y, mat.m12 * z)); 651 double rz = Math.fma(mat.m20, x, Math.fma(mat.m21, y, mat.m22 * z)); 652 dest.x = rx; 653 dest.y = ry; 654 dest.z = rz; 655 return dest; 656 } 657 658 /** 659 * Multiply the given 4x4 matrix <code>mat</code> with <code>this</code>. 660 * <p> 661 * This method assumes the <code>w</code> component of <code>this</code> to be <code>1.0</code>. 662 * 663 * @param mat 664 * the matrix to multiply this vector by 665 * @return this 666 */ 667 ref public Vector3d mulPosition(Matrix4d mat) return { 668 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30))); 669 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31))); 670 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32))); 671 this.x = rx; 672 this.y = ry; 673 this.z = rz; 674 return this; 675 } 676 677 /** 678 * Multiply the given 4x3 matrix <code>mat</code> with <code>this</code>. 679 * <p> 680 * This method assumes the <code>w</code> component of <code>this</code> to be <code>1.0</code>. 681 * 682 * @param mat 683 * the matrix to multiply this vector by 684 * @return this 685 */ 686 ref public Vector3d mulPosition(Matrix4x3d mat) return { 687 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30))); 688 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31))); 689 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32))); 690 this.x = rx; 691 this.y = ry; 692 this.z = rz; 693 return this; 694 } 695 696 697 public Vector3d mulPosition(Matrix4d mat, ref Vector3d dest) { 698 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30))); 699 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31))); 700 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32))); 701 dest.x = rx; 702 dest.y = ry; 703 dest.z = rz; 704 return dest; 705 } 706 707 public Vector3d mulPosition(Matrix4x3d mat, ref Vector3d dest) { 708 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30))); 709 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31))); 710 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32))); 711 dest.x = rx; 712 dest.y = ry; 713 dest.z = rz; 714 return dest; 715 } 716 717 /** 718 * Multiply the transpose of the given 4x4 matrix <code>mat</code> with <code>this</code>. 719 * <p> 720 * This method assumes the <code>w</code> component of <code>this</code> to be <code>1.0</code>. 721 * 722 * @param mat 723 * the matrix whose transpose to multiply this vector by 724 * @return this 725 */ 726 ref public Vector3d mulTransposePosition(Matrix4d mat) return { 727 double rx = Math.fma(mat.m00, x, Math.fma(mat.m01, y, Math.fma(mat.m02, z, mat.m03))); 728 double ry = Math.fma(mat.m10, x, Math.fma(mat.m11, y, Math.fma(mat.m12, z, mat.m13))); 729 double rz = Math.fma(mat.m20, x, Math.fma(mat.m21, y, Math.fma(mat.m22, z, mat.m23))); 730 this.x = rx; 731 this.y = ry; 732 this.z = rz; 733 return this; 734 } 735 736 public Vector3d mulTransposePosition(Matrix4d mat, ref Vector3d dest) { 737 double rx = Math.fma(mat.m00, x, Math.fma(mat.m01, y, Math.fma(mat.m02, z, mat.m03))); 738 double ry = Math.fma(mat.m10, x, Math.fma(mat.m11, y, Math.fma(mat.m12, z, mat.m13))); 739 double rz = Math.fma(mat.m20, x, Math.fma(mat.m21, y, Math.fma(mat.m22, z, mat.m23))); 740 dest.x = rx; 741 dest.y = ry; 742 dest.z = rz; 743 return dest; 744 } 745 746 747 748 749 /** 750 * Multiply the given 4x4 matrix <code>mat</code> with <code>this</code> and return the <i>w</i> component 751 * of the resulting 4D vector. 752 * <p> 753 * This method assumes the <code>w</code> component of <code>this</code> to be <code>1.0</code>. 754 * 755 * @param mat 756 * the matrix to multiply this vector by 757 * @return the <i>w</i> component of the resulting 4D vector after multiplication 758 */ 759 public double mulPositionW(Matrix4d mat) { 760 double w = Math.fma(mat.m03, x, Math.fma(mat.m13, y, Math.fma(mat.m23, z, mat.m33))); 761 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30))); 762 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31))); 763 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32))); 764 this.x = rx; 765 this.y = ry; 766 this.z = rz; 767 return w; 768 } 769 770 public double mulPositionW(Matrix4d mat, ref Vector3d dest) { 771 double w = Math.fma(mat.m03, x, Math.fma(mat.m13, y, Math.fma(mat.m23, z, mat.m33))); 772 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30))); 773 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31))); 774 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32))); 775 dest.x = rx; 776 dest.y = ry; 777 dest.z = rz; 778 return w; 779 } 780 781 782 /** 783 * Multiply the given 4x4 matrix <code>mat</code> with <code>this</code>. 784 * <p> 785 * This method assumes the <code>w</code> component of <code>this</code> to be <code>0.0</code>. 786 * 787 * @param mat 788 * the matrix to multiply this vector by 789 * @return this 790 */ 791 ref public Vector3d mulDirection(Matrix4d mat) return { 792 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z)); 793 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z)); 794 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, mat.m22 * z)); 795 this.x = rx; 796 this.y = ry; 797 this.z = rz; 798 return this; 799 } 800 801 /** 802 * Multiply the given 4x3 matrix <code>mat</code> with <code>this</code>. 803 * <p> 804 * This method assumes the <code>w</code> component of <code>this</code> to be <code>0.0</code>. 805 * 806 * @param mat 807 * the matrix to multiply this vector by 808 * @return this 809 */ 810 ref public Vector3d mulDirection(Matrix4x3d mat) return { 811 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z)); 812 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z)); 813 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, mat.m22 * z)); 814 this.x = rx; 815 this.y = ry; 816 this.z = rz; 817 return this; 818 } 819 820 821 public Vector3d mulDirection(Matrix4d mat, Vector3d dest) { 822 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z)); 823 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z)); 824 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, mat.m22 * z)); 825 dest.x = rx; 826 dest.y = ry; 827 dest.z = rz; 828 return dest; 829 } 830 831 public Vector3d mulDirection(Matrix4x3d mat, ref Vector3d dest) { 832 double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z)); 833 double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z)); 834 double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, mat.m22 * z)); 835 dest.x = rx; 836 dest.y = ry; 837 dest.z = rz; 838 return dest; 839 } 840 841 842 /** 843 * Multiply the transpose of the given 4x4 matrix <code>mat</code> with <code>this</code>. 844 * <p> 845 * This method assumes the <code>w</code> component of <code>this</code> to be <code>0.0</code>. 846 * 847 * @param mat 848 * the matrix whose transpose to multiply this vector by 849 * @return this 850 */ 851 ref public Vector3d mulTransposeDirection(Matrix4d mat) return { 852 double rx = Math.fma(mat.m00, x, Math.fma(mat.m01, y, mat.m02 * z)); 853 double ry = Math.fma(mat.m10, x, Math.fma(mat.m11, y, mat.m12 * z)); 854 double rz = Math.fma(mat.m20, x, Math.fma(mat.m21, y, mat.m22 * z)); 855 this.x = rx; 856 this.y = ry; 857 this.z = rz; 858 return this; 859 } 860 861 public Vector3d mulTransposeDirection(Matrix4d mat, ref Vector3d dest) { 862 double rx = Math.fma(mat.m00, x, Math.fma(mat.m01, y, mat.m02 * z)); 863 double ry = Math.fma(mat.m10, x, Math.fma(mat.m11, y, mat.m12 * z)); 864 double rz = Math.fma(mat.m20, x, Math.fma(mat.m21, y, mat.m22 * z)); 865 dest.x = rx; 866 dest.y = ry; 867 dest.z = rz; 868 return dest; 869 } 870 871 /** 872 * Multiply this Vector3d by the given scalar value. 873 * 874 * @param scalar 875 * the scalar to multiply this vector by 876 * @return this 877 */ 878 ref public Vector3d mul(double scalar) return { 879 this.x = x * scalar; 880 this.y = y * scalar; 881 this.z = z * scalar; 882 return this; 883 } 884 885 public Vector3d mul(double scalar, ref Vector3d dest) { 886 dest.x = x * scalar; 887 dest.y = y * scalar; 888 dest.z = z * scalar; 889 return dest; 890 } 891 892 /** 893 * Multiply the components of this Vector3d by the given scalar values and store the result in <code>this</code>. 894 * 895 * @param x 896 * the x component to multiply this vector by 897 * @param y 898 * the y component to multiply this vector by 899 * @param z 900 * the z component to multiply this vector by 901 * @return this 902 */ 903 ref public Vector3d mul(double x, double y, double z) return { 904 this.x = this.x * x; 905 this.y = this.y * y; 906 this.z = this.z * z; 907 return this; 908 } 909 910 public Vector3d mul(double x, double y, double z, ref Vector3d dest) { 911 dest.x = this.x * x; 912 dest.y = this.y * y; 913 dest.z = this.z * z; 914 return dest; 915 } 916 917 /** 918 * Rotate this vector by the given quaternion <code>quat</code> and store the result in <code>this</code>. 919 * 920 * @see Quaterniond#transform(Vector3d) 921 * 922 * @param quat 923 * the quaternion to rotate this vector 924 * @return this 925 */ 926 ref public Vector3d rotate(Quaterniond quat) return { 927 quat.transform(this, this); 928 return this; 929 } 930 931 public Vector3d rotate(Quaterniond quat, ref Vector3d dest) { 932 return quat.transform(this, dest); 933 } 934 935 public Quaterniond rotationTo(Vector3d toDir, ref Quaterniond dest) { 936 return dest.rotationTo(this, toDir); 937 } 938 939 public Quaterniond rotationTo(double toDirX, double toDirY, double toDirZ, ref Quaterniond dest) { 940 return dest.rotationTo(x, y, z, toDirX, toDirY, toDirZ); 941 } 942 943 /** 944 * Rotate this vector the specified radians around the given rotation axis. 945 * 946 * @param angle 947 * the angle in radians 948 * @param x 949 * the x component of the rotation axis 950 * @param y 951 * the y component of the rotation axis 952 * @param z 953 * the z component of the rotation axis 954 * @return this 955 */ 956 ref public Vector3d rotateAxis(double angle, double x, double y, double z) return { 957 if (y == 0.0 && z == 0.0 && Math.absEqualsOne(x)) 958 rotateX(x * angle, this); 959 else if (x == 0.0 && z == 0.0 && Math.absEqualsOne(y)) 960 rotateY(y * angle, this); 961 else if (x == 0.0 && y == 0.0 && Math.absEqualsOne(z)) 962 rotateZ(z * angle, this); 963 else 964 rotateAxisInternal(angle, x, y, z, this); 965 966 return this; 967 } 968 969 public Vector3d rotateAxis(double angle, double aX, double aY, double aZ, ref Vector3d dest) { 970 if (aY == 0.0 && aZ == 0.0 && Math.absEqualsOne(aX)) 971 return rotateX(aX * angle, dest); 972 else if (aX == 0.0 && aZ == 0.0 && Math.absEqualsOne(aY)) 973 return rotateY(aY * angle, dest); 974 else if (aX == 0.0 && aY == 0.0 && Math.absEqualsOne(aZ)) 975 return rotateZ(aZ * angle, dest); 976 return rotateAxisInternal(angle, aX, aY, aZ, dest); 977 } 978 979 private Vector3d rotateAxisInternal(double angle, double aX, double aY, double aZ, ref Vector3d dest) { 980 double hangle = angle * 0.5; 981 double sinAngle = Math.sin(hangle); 982 double qx = aX * sinAngle, qy = aY * sinAngle, qz = aZ * sinAngle; 983 double qw = Math.cosFromSin(sinAngle, hangle); 984 double w2 = qw * qw, x2 = qx * qx, y2 = qy * qy, z2 = qz * qz, zw = qz * qw; 985 double xy = qx * qy, xz = qx * qz, yw = qy * qw, yz = qy * qz, xw = qx * qw; 986 double nx = (w2 + x2 - z2 - y2) * x + (-zw + xy - zw + xy) * y + (yw + xz + xz + yw) * z; 987 double ny = (xy + zw + zw + xy) * x + ( y2 - z2 + w2 - x2) * y + (yz + yz - xw - xw) * z; 988 double nz = (xz - yw + xz - yw) * x + ( yz + yz + xw + xw) * y + (z2 - y2 - x2 + w2) * z; 989 dest.x = nx; 990 dest.y = ny; 991 dest.z = nz; 992 return dest; 993 } 994 995 /** 996 * Rotate this vector the specified radians around the X axis. 997 * 998 * @param angle 999 * the angle in radians 1000 * @return this 1001 */ 1002 ref public Vector3d rotateX(double angle) return { 1003 double sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); 1004 double y = this.y * cos - this.z * sin; 1005 double z = this.y * sin + this.z * cos; 1006 this.y = y; 1007 this.z = z; 1008 return this; 1009 } 1010 1011 public Vector3d rotateX(double angle, ref Vector3d dest) { 1012 double sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); 1013 double y = this.y * cos - this.z * sin; 1014 double z = this.y * sin + this.z * cos; 1015 dest.x = this.x; 1016 dest.y = y; 1017 dest.z = z; 1018 return dest; 1019 } 1020 1021 /** 1022 * Rotate this vector the specified radians around the Y axis. 1023 * 1024 * @param angle 1025 * the angle in radians 1026 * @return this 1027 */ 1028 ref public Vector3d rotateY(double angle) return { 1029 double sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); 1030 double x = this.x * cos + this.z * sin; 1031 double z = -this.x * sin + this.z * cos; 1032 this.x = x; 1033 this.z = z; 1034 return this; 1035 } 1036 1037 public Vector3d rotateY(double angle, ref Vector3d dest) { 1038 double sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); 1039 double x = this.x * cos + this.z * sin; 1040 double z = -this.x * sin + this.z * cos; 1041 dest.x = x; 1042 dest.y = this.y; 1043 dest.z = z; 1044 return dest; 1045 } 1046 1047 /** 1048 * Rotate this vector the specified radians around the Z axis. 1049 * 1050 * @param angle 1051 * the angle in radians 1052 * @return this 1053 */ 1054 ref public Vector3d rotateZ(double angle) return { 1055 double sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); 1056 double x = this.x * cos - this.y * sin; 1057 double y = this.x * sin + this.y * cos; 1058 this.x = x; 1059 this.y = y; 1060 return this; 1061 } 1062 1063 public Vector3d rotateZ(double angle, ref Vector3d dest) { 1064 double sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle); 1065 double x = this.x * cos - this.y * sin; 1066 double y = this.x * sin + this.y * cos; 1067 dest.x = x; 1068 dest.y = y; 1069 dest.z = this.z; 1070 return dest; 1071 } 1072 1073 /** 1074 * Divide this Vector3d by the given scalar value. 1075 * 1076 * @param scalar 1077 * the scalar to divide this vector by 1078 * @return this 1079 */ 1080 ref public Vector3d div(double scalar) return { 1081 double inv = 1.0 / scalar; 1082 this.x = x * inv; 1083 this.y = y * inv; 1084 this.z = z * inv; 1085 return this; 1086 } 1087 1088 public Vector3d div(double scalar, ref Vector3d dest) { 1089 double inv = 1.0 / scalar; 1090 dest.x = x * inv; 1091 dest.y = y * inv; 1092 dest.z = z * inv; 1093 return dest; 1094 } 1095 1096 /** 1097 * Divide the components of this Vector3d by the given scalar values and store the result in <code>this</code>. 1098 * 1099 * @param x 1100 * the x component to divide this vector by 1101 * @param y 1102 * the y component to divide this vector by 1103 * @param z 1104 * the z component to divide this vector by 1105 * @return this 1106 */ 1107 ref public Vector3d div(double x, double y, double z) return { 1108 this.x = this.x / x; 1109 this.y = this.y / y; 1110 this.z = this.z / z; 1111 return this; 1112 } 1113 1114 public Vector3d div(double x, double y, double z, ref Vector3d dest) { 1115 dest.x = this.x / x; 1116 dest.y = this.y / y; 1117 dest.z = this.z / z; 1118 return dest; 1119 } 1120 1121 public double lengthSquared() { 1122 return Math.fma(x, x, Math.fma(y, y, z * z)); 1123 } 1124 1125 /** 1126 * Get the length squared of a 3-dimensional double-precision vector. 1127 * 1128 * @param x The vector's x component 1129 * @param y The vector's y component 1130 * @param z The vector's z component 1131 * 1132 * @return the length squared of the given vector 1133 * 1134 * @author F. Neurath 1135 */ 1136 public static double lengthSquared(double x, double y, double z) { 1137 return Math.fma(x, x, Math.fma(y, y, z * z)); 1138 } 1139 1140 public double length() { 1141 return Math.sqrt(Math.fma(x, x, Math.fma(y, y, z * z))); 1142 } 1143 1144 /** 1145 * Get the length of a 3-dimensional double-precision vector. 1146 * 1147 * @param x The vector's x component 1148 * @param y The vector's y component 1149 * @param z The vector's z component 1150 * 1151 * @return the length of the given vector 1152 * 1153 * @author F. Neurath 1154 */ 1155 public static double length(double x, double y, double z) { 1156 return Math.sqrt(Math.fma(x, x, Math.fma(y, y, z * z))); 1157 } 1158 1159 /** 1160 * Normalize this vector. 1161 * 1162 * @return this 1163 */ 1164 ref public Vector3d normalize() return { 1165 double invLength = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z))); 1166 this.x = x * invLength; 1167 this.y = y * invLength; 1168 this.z = z * invLength; 1169 return this; 1170 } 1171 1172 public Vector3d normalize(ref Vector3d dest) { 1173 double invLength = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z))); 1174 dest.x = x * invLength; 1175 dest.y = y * invLength; 1176 dest.z = z * invLength; 1177 return dest; 1178 } 1179 1180 /** 1181 * Scale this vector to have the given length. 1182 * 1183 * @param length 1184 * the desired length 1185 * @return this 1186 */ 1187 ref public Vector3d normalize(double length) return { 1188 double invLength = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z))) * length; 1189 this.x = x * invLength; 1190 this.y = y * invLength; 1191 this.z = z * invLength; 1192 return this; 1193 } 1194 1195 public Vector3d normalize(double length, ref Vector3d dest) { 1196 double invLength = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z))) * length; 1197 dest.x = x * invLength; 1198 dest.y = y * invLength; 1199 dest.z = z * invLength; 1200 return dest; 1201 } 1202 1203 /** 1204 * Set this vector to be the cross product of this and v2. 1205 * 1206 * @param v 1207 * the other vector 1208 * @return this 1209 */ 1210 ref public Vector3d cross(Vector3d v) return { 1211 double rx = Math.fma(y, v.z, -z * v.y); 1212 double ry = Math.fma(z, v.x, -x * v.z); 1213 double rz = Math.fma(x, v.y, -y * v.x); 1214 this.x = rx; 1215 this.y = ry; 1216 this.z = rz; 1217 return this; 1218 } 1219 1220 /** 1221 * Set this vector to be the cross product of itself and <code>(x, y, z)</code>. 1222 * 1223 * @param x 1224 * the x component of the other vector 1225 * @param y 1226 * the y component of the other vector 1227 * @param z 1228 * the z component of the other vector 1229 * @return this 1230 */ 1231 ref public Vector3d cross(double x, double y, double z) return { 1232 double rx = Math.fma(this.y, z, -this.z * y); 1233 double ry = Math.fma(this.z, x, -this.x * z); 1234 double rz = Math.fma(this.x, y, -this.y * x); 1235 this.x = rx; 1236 this.y = ry; 1237 this.z = rz; 1238 return this; 1239 } 1240 1241 public Vector3d cross(Vector3d v, ref Vector3d dest) { 1242 double rx = Math.fma(y, v.z, -z * v.y); 1243 double ry = Math.fma(z, v.x, -x * v.z); 1244 double rz = Math.fma(x, v.y, -y * v.x); 1245 dest.x = rx; 1246 dest.y = ry; 1247 dest.z = rz; 1248 return dest; 1249 } 1250 1251 public Vector3d cross(double x, double y, double z, ref Vector3d dest) { 1252 double rx = Math.fma(this.y, z, -this.z * y); 1253 double ry = Math.fma(this.z, x, -this.x * z); 1254 double rz = Math.fma(this.x, y, -this.y * x); 1255 dest.x = rx; 1256 dest.y = ry; 1257 dest.z = rz; 1258 return dest; 1259 } 1260 1261 public double distance(Vector3d v) { 1262 double dx = this.x - v.x; 1263 double dy = this.y - v.y; 1264 double dz = this.z - v.z; 1265 return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, dz * dz))); 1266 } 1267 1268 public double distance(double x, double y, double z) { 1269 double dx = this.x - x; 1270 double dy = this.y - y; 1271 double dz = this.z - z; 1272 return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, dz * dz))); 1273 } 1274 1275 public double distanceSquared(Vector3d v) { 1276 double dx = this.x - v.x; 1277 double dy = this.y - v.y; 1278 double dz = this.z - v.z; 1279 return Math.fma(dx, dx, Math.fma(dy, dy, dz * dz)); 1280 } 1281 1282 public double distanceSquared(double x, double y, double z) { 1283 double dx = this.x - x; 1284 double dy = this.y - y; 1285 double dz = this.z - z; 1286 return Math.fma(dx, dx, Math.fma(dy, dy, dz * dz)); 1287 } 1288 1289 /** 1290 * Return the distance between <code>(x1, y1, z1)</code> and <code>(x2, y2, z2)</code>. 1291 * 1292 * @param x1 1293 * the x component of the first vector 1294 * @param y1 1295 * the y component of the first vector 1296 * @param z1 1297 * the z component of the first vector 1298 * @param x2 1299 * the x component of the second vector 1300 * @param y2 1301 * the y component of the second vector 1302 * @param z2 1303 * the z component of the second vector 1304 * @return the euclidean distance 1305 */ 1306 public static double distance(double x1, double y1, double z1, double x2, double y2, double z2) { 1307 return Math.sqrt(distanceSquared(x1, y1, z1, x2, y2, z2)); 1308 } 1309 1310 /** 1311 * Return the squared distance between <code>(x1, y1, z1)</code> and <code>(x2, y2, z2)</code>. 1312 * 1313 * @param x1 1314 * the x component of the first vector 1315 * @param y1 1316 * the y component of the first vector 1317 * @param z1 1318 * the z component of the first vector 1319 * @param x2 1320 * the x component of the second vector 1321 * @param y2 1322 * the y component of the second vector 1323 * @param z2 1324 * the z component of the second vector 1325 * @return the euclidean distance squared 1326 */ 1327 public static double distanceSquared(double x1, double y1, double z1, double x2, double y2, double z2) { 1328 double dx = x1 - x2; 1329 double dy = y1 - y2; 1330 double dz = z1 - z2; 1331 return Math.fma(dx, dx, Math.fma(dy, dy, dz * dz)); 1332 } 1333 1334 public double dot(Vector3d v) { 1335 return Math.fma(this.x, v.x, Math.fma(this.y, v.y, this.z * v.z)); 1336 } 1337 1338 public double dot(double x, double y, double z) { 1339 return Math.fma(this.x, x, Math.fma(this.y, y, this.z * z)); 1340 } 1341 1342 public double angleCos(Vector3d v) { 1343 double length1Squared = Math.fma(x, x, Math.fma(y, y, z * z)); 1344 double length2Squared = Math.fma(v.x, v.x, Math.fma(v.y, v.y, v.z * v.z)); 1345 double dot = Math.fma(x, v.x, Math.fma(y, v.y, z * v.z)); 1346 return dot / Math.sqrt(length1Squared * length2Squared); 1347 } 1348 1349 public double angle(Vector3d v) { 1350 double cos = angleCos(v); 1351 // This is because sometimes cos goes above 1 or below -1 because of lost precision 1352 cos = cos < 1 ? cos : 1; 1353 cos = cos > -1 ? cos : -1; 1354 return Math.acos(cos); 1355 } 1356 1357 public double angleSigned(Vector3d v, Vector3d n) { 1358 double x = v.x; 1359 double y = v.y; 1360 double z = v.z; 1361 return Math.atan2( 1362 (this.y * z - this.z * y) * n.x + (this.z * x - this.x * z) * n.y + (this.x * y - this.y * x) * n.z, 1363 this.x * x + this.y * y + this.z * z); 1364 } 1365 1366 public double angleSigned(double x, double y, double z, double nx, double ny, double nz) { 1367 return Math.atan2( 1368 (this.y * z - this.z * y) * nx + (this.z * x - this.x * z) * ny + (this.x * y - this.y * x) * nz, 1369 this.x * x + this.y * y + this.z * z); 1370 } 1371 1372 /** 1373 * Set the components of this vector to be the component-wise minimum of this and the other vector. 1374 * 1375 * @param v 1376 * the other vector 1377 * @return this 1378 */ 1379 ref public Vector3d min(Vector3d v) return { 1380 this.x = x < v.x ? x : v.x; 1381 this.y = y < v.y ? y : v.y; 1382 this.z = z < v.z ? z : v.z; 1383 return this; 1384 } 1385 1386 public Vector3d min(Vector3d v, ref Vector3d dest) { 1387 dest.x = x < v.x ? x : v.x; 1388 dest.y = y < v.y ? y : v.y; 1389 dest.z = z < v.z ? z : v.z; 1390 return dest; 1391 } 1392 1393 /** 1394 * Set the components of this vector to be the component-wise maximum of this and the other vector. 1395 * 1396 * @param v 1397 * the other vector 1398 * @return this 1399 */ 1400 ref public Vector3d max(Vector3d v) return { 1401 this.x = x > v.x ? x : v.x; 1402 this.y = y > v.y ? y : v.y; 1403 this.z = z > v.z ? z : v.z; 1404 return this; 1405 } 1406 1407 public Vector3d max(Vector3d v, ref Vector3d dest) { 1408 dest.x = x > v.x ? x : v.x; 1409 dest.y = y > v.y ? y : v.y; 1410 dest.z = z > v.z ? z : v.z; 1411 return dest; 1412 } 1413 1414 /** 1415 * Set all components to zero. 1416 * 1417 * @return this 1418 */ 1419 ref public Vector3d zero() return { 1420 this.x = 0; 1421 this.y = 0; 1422 this.z = 0; 1423 return this; 1424 } 1425 1426 /** 1427 * Negate this vector. 1428 * 1429 * @return this 1430 */ 1431 ref public Vector3d negate() return { 1432 this.x = -x; 1433 this.y = -y; 1434 this.z = -z; 1435 return this; 1436 } 1437 1438 public Vector3d negate(ref Vector3d dest) { 1439 dest.x = -x; 1440 dest.y = -y; 1441 dest.z = -z; 1442 return dest; 1443 } 1444 1445 /** 1446 * Set <code>this</code> vector's components to their respective absolute values. 1447 * 1448 * @return this 1449 */ 1450 ref public Vector3d absolute() return { 1451 this.x = Math.abs(this.x); 1452 this.y = Math.abs(this.y); 1453 this.z = Math.abs(this.z); 1454 return this; 1455 } 1456 1457 public Vector3d absolute(ref Vector3d dest) { 1458 dest.x = Math.abs(this.x); 1459 dest.y = Math.abs(this.y); 1460 dest.z = Math.abs(this.z); 1461 return dest; 1462 } 1463 1464 public int hashCode() { 1465 immutable int prime = 31; 1466 int result = 1; 1467 long temp; 1468 temp = Math.doubleToLongBits(x); 1469 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 1470 temp = Math.doubleToLongBits(y); 1471 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 1472 temp = Math.doubleToLongBits(z); 1473 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 1474 return result; 1475 } 1476 1477 1478 public bool equals(Vector3d v, double delta) { 1479 if (this == v) 1480 return true; 1481 if (!Math.equals(x, v.x, delta)) 1482 return false; 1483 if (!Math.equals(y, v.y, delta)) 1484 return false; 1485 if (!Math.equals(z, v.z, delta)) 1486 return false; 1487 return true; 1488 } 1489 1490 public bool equals(double x, double y, double z) { 1491 if (Math.doubleToLongBits(this.x) != Math.doubleToLongBits(x)) 1492 return false; 1493 if (Math.doubleToLongBits(this.y) != Math.doubleToLongBits(y)) 1494 return false; 1495 if (Math.doubleToLongBits(this.z) != Math.doubleToLongBits(z)) 1496 return false; 1497 return true; 1498 } 1499 1500 public bool equals(Vector3d other) { 1501 if (Math.doubleToLongBits(this.x) != Math.doubleToLongBits(other.x)) 1502 return false; 1503 if (Math.doubleToLongBits(this.y) != Math.doubleToLongBits(other.y)) 1504 return false; 1505 if (Math.doubleToLongBits(this.z) != Math.doubleToLongBits(other.z)) 1506 return false; 1507 return true; 1508 } 1509 1510 /** 1511 * Reflect this vector about the given normal vector. 1512 * 1513 * @param normal 1514 * the vector to reflect about 1515 * @return this 1516 */ 1517 ref public Vector3d reflect(Vector3d normal) return { 1518 double x = normal.x; 1519 double y = normal.y; 1520 double z = normal.z; 1521 double dot = Math.fma(this.x, x, Math.fma(this.y, y, this.z * z)); 1522 this.x = this.x - (dot + dot) * x; 1523 this.y = this.y - (dot + dot) * y; 1524 this.z = this.z - (dot + dot) * z; 1525 return this; 1526 } 1527 1528 /** 1529 * Reflect this vector about the given normal vector. 1530 * 1531 * @param x 1532 * the x component of the normal 1533 * @param y 1534 * the y component of the normal 1535 * @param z 1536 * the z component of the normal 1537 * @return this 1538 */ 1539 ref public Vector3d reflect(double x, double y, double z) return { 1540 double dot = Math.fma(this.x, x, Math.fma(this.y, y, this.z * z)); 1541 this.x = this.x - (dot + dot) * x; 1542 this.y = this.y - (dot + dot) * y; 1543 this.z = this.z - (dot + dot) * z; 1544 return this; 1545 } 1546 1547 public Vector3d reflect(Vector3d normal, ref Vector3d dest) { 1548 double x = normal.x; 1549 double y = normal.y; 1550 double z = normal.z; 1551 double dot = Math.fma(this.x, x, Math.fma(this.y, y, this.z * z)); 1552 dest.x = this.x - (dot + dot) * x; 1553 dest.y = this.y - (dot + dot) * y; 1554 dest.z = this.z - (dot + dot) * z; 1555 return dest; 1556 } 1557 1558 public Vector3d reflect(double x, double y, double z, ref Vector3d dest) { 1559 double dot = Math.fma(this.x, x, Math.fma(this.y, y, this.z * z)); 1560 dest.x = this.x - (dot + dot) * x; 1561 dest.y = this.y - (dot + dot) * y; 1562 dest.z = this.z - (dot + dot) * z; 1563 return dest; 1564 } 1565 1566 /** 1567 * Compute the half vector between this and the other vector. 1568 * 1569 * @param other 1570 * the other vector 1571 * @return this 1572 */ 1573 ref public Vector3d half(Vector3d other) return { 1574 return this.set(this).add(other.x, other.y, other.z).normalize(); 1575 } 1576 1577 /** 1578 * Compute the half vector between this and the vector <code>(x, y, z)</code>. 1579 * 1580 * @param x 1581 * the x component of the other vector 1582 * @param y 1583 * the y component of the other vector 1584 * @param z 1585 * the z component of the other vector 1586 * @return this 1587 */ 1588 ref public Vector3d half(double x, double y, double z) return { 1589 return this.set(this).add(x, y, z).normalize(); 1590 } 1591 1592 public Vector3d half(Vector3d other, ref Vector3d dest) { 1593 return dest.set(this).add(other.x, other.y, other.z).normalize(); 1594 } 1595 1596 public Vector3d half(double x, double y, double z, ref Vector3d dest) { 1597 return dest.set(this).add(x, y, z).normalize(); 1598 } 1599 1600 public Vector3d smoothStep(Vector3d v, double t, ref Vector3d dest) { 1601 double t2 = t * t; 1602 double t3 = t2 * t; 1603 dest.x = (x + x - v.x - v.x) * t3 + (3.0 * v.x - 3.0 * x) * t2 + x * t + x; 1604 dest.y = (y + y - v.y - v.y) * t3 + (3.0 * v.y - 3.0 * y) * t2 + y * t + y; 1605 dest.z = (z + z - v.z - v.z) * t3 + (3.0 * v.z - 3.0 * z) * t2 + z * t + z; 1606 return dest; 1607 } 1608 1609 public Vector3d hermite(Vector3d t0, Vector3d v1, Vector3d t1, double t, ref Vector3d dest) { 1610 double t2 = t * t; 1611 double t3 = t2 * t; 1612 dest.x = (x + x - v1.x - v1.x + t1.x + t0.x) * t3 + (3.0 * v1.x - 3.0 * x - t0.x - t0.x - t1.x) * t2 + x * t + x; 1613 dest.y = (y + y - v1.y - v1.y + t1.y + t0.y) * t3 + (3.0 * v1.y - 3.0 * y - t0.y - t0.y - t1.y) * t2 + y * t + y; 1614 dest.z = (z + z - v1.z - v1.z + t1.z + t0.z) * t3 + (3.0 * v1.z - 3.0 * z - t0.z - t0.z - t1.z) * t2 + z * t + z; 1615 return dest; 1616 } 1617 1618 /** 1619 * Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code> 1620 * and store the result in <code>this</code>. 1621 * <p> 1622 * 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> 1623 * then the result is <code>other</code>. 1624 * 1625 * @param other 1626 * the other vector 1627 * @param t 1628 * the interpolation factor between 0.0 and 1.0 1629 * @return this 1630 */ 1631 ref public Vector3d lerp(Vector3d other, double t) return { 1632 this.x = Math.fma(other.x - x, t, x); 1633 this.y = Math.fma(other.y - y, t, y); 1634 this.z = Math.fma(other.z - z, t, z); 1635 return this; 1636 } 1637 1638 public Vector3d lerp(Vector3d other, double t, ref Vector3d dest) { 1639 dest.x = Math.fma(other.x - x, t, x); 1640 dest.y = Math.fma(other.y - y, t, y); 1641 dest.z = Math.fma(other.z - z, t, z); 1642 return dest; 1643 } 1644 1645 public double get(int component) { 1646 switch (component) { 1647 case 0: 1648 return x; 1649 case 1: 1650 return y; 1651 case 2: 1652 return z; 1653 default: 1654 return 0; 1655 } 1656 } 1657 1658 public Vector3i get(int mode, ref Vector3i dest) { 1659 dest.x = Math.roundUsing(this.x, mode); 1660 dest.y = Math.roundUsing(this.y, mode); 1661 dest.z = Math.roundUsing(this.z, mode); 1662 return dest; 1663 } 1664 1665 public Vector3d get(ref Vector3d dest) { 1666 dest.x = this.x; 1667 dest.y = this.y; 1668 dest.z = this.z; 1669 return dest; 1670 } 1671 1672 public int maxComponent() { 1673 double absX = Math.abs(x); 1674 double absY = Math.abs(y); 1675 double absZ = Math.abs(z); 1676 if (absX >= absY && absX >= absZ) { 1677 return 0; 1678 } else if (absY >= absZ) { 1679 return 1; 1680 } 1681 return 2; 1682 } 1683 1684 public int minComponent() { 1685 double absX = Math.abs(x); 1686 double absY = Math.abs(y); 1687 double absZ = Math.abs(z); 1688 if (absX < absY && absX < absZ) { 1689 return 0; 1690 } else if (absY < absZ) { 1691 return 1; 1692 } 1693 return 2; 1694 } 1695 1696 public Vector3d orthogonalize(Vector3d v, ref Vector3d dest) { 1697 /* 1698 * http://lolengine.net/blog/2013/09/21/picking-orthogonal-vector-combing-coconuts 1699 */ 1700 double rx, ry, rz; 1701 if (Math.abs(v.x) > Math.abs(v.z)) { 1702 rx = -v.y; 1703 ry = v.x; 1704 rz = 0.0; 1705 } else { 1706 rx = 0.0; 1707 ry = -v.z; 1708 rz = v.y; 1709 } 1710 double invLen = Math.invsqrt(rx * rx + ry * ry + rz * rz); 1711 dest.x = rx * invLen; 1712 dest.y = ry * invLen; 1713 dest.z = rz * invLen; 1714 return dest; 1715 } 1716 1717 /** 1718 * Transform <code>this</code> vector so that it is orthogonal to the given vector <code>v</code> and normalize the result. 1719 * <p> 1720 * Reference: <a href="https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process">Gram–Schmidt process</a> 1721 * 1722 * @param v 1723 * the reference vector which the result should be orthogonal to 1724 * @return this 1725 */ 1726 ref public Vector3d orthogonalize(Vector3d v) return { 1727 orthogonalize(v, this); 1728 return this; 1729 } 1730 1731 public Vector3d orthogonalizeUnit(Vector3d v, ref Vector3d dest) { 1732 return orthogonalize(v, dest); 1733 } 1734 1735 /** 1736 * Transform <code>this</code> vector so that it is orthogonal to the given unit vector <code>v</code> and normalize the result. 1737 * <p> 1738 * The vector <code>v</code> is assumed to be a {@link #normalize() unit} vector. 1739 * <p> 1740 * Reference: <a href="https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process">Gram–Schmidt process</a> 1741 * 1742 * @param v 1743 * the reference unit vector which the result should be orthogonal to 1744 * @return this 1745 */ 1746 ref public Vector3d orthogonalizeUnit(Vector3d v) return { 1747 orthogonalizeUnit(v, this); 1748 return this; 1749 } 1750 1751 /** 1752 * Set each component of this vector to the largest (closest to positive 1753 * infinity) {@code double} value that is less than or equal to that 1754 * component and is equal to a mathematical integer. 1755 * 1756 * @return this 1757 */ 1758 ref public Vector3d floor() return { 1759 this.x = Math.floor(x); 1760 this.y = Math.floor(y); 1761 this.z = Math.floor(z); 1762 return this; 1763 } 1764 1765 public Vector3d floor(ref Vector3d dest) { 1766 dest.x = Math.floor(x); 1767 dest.y = Math.floor(y); 1768 dest.z = Math.floor(z); 1769 return dest; 1770 } 1771 1772 /** 1773 * Set each component of this vector to the smallest (closest to negative 1774 * infinity) {@code double} value that is greater than or equal to that 1775 * component and is equal to a mathematical integer. 1776 * 1777 * @return this 1778 */ 1779 ref public Vector3d ceil() return { 1780 this.x = Math.ceil(x); 1781 this.y = Math.ceil(y); 1782 this.z = Math.ceil(z); 1783 return this; 1784 } 1785 1786 public Vector3d ceil(ref Vector3d dest) { 1787 dest.x = Math.ceil(x); 1788 dest.y = Math.ceil(y); 1789 dest.z = Math.ceil(z); 1790 return dest; 1791 } 1792 1793 /** 1794 * Set each component of this vector to the closest double that is equal to 1795 * a mathematical integer, with ties rounding to positive infinity. 1796 * 1797 * @return this 1798 */ 1799 ref public Vector3d round() return { 1800 this.x = Math.round(x); 1801 this.y = Math.round(y); 1802 this.z = Math.round(z); 1803 return this; 1804 } 1805 1806 public Vector3d round(ref Vector3d dest) { 1807 dest.x = Math.round(x); 1808 dest.y = Math.round(y); 1809 dest.z = Math.round(z); 1810 return dest; 1811 } 1812 1813 public bool isFinite() { 1814 return Math.isFinite(x) && Math.isFinite(y) && Math.isFinite(z); 1815 } 1816 }