1 /////////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas 4 // Digital Ltd. LLC 5 // 6 // All rights reserved. 7 // 8 // Redistribution and use in source and binary forms, with or without 9 // modification, are permitted provided that the following conditions are 10 // met: 11 // * Redistributions of source code must retain the above copyright 12 // notice, this list of conditions and the following disclaimer. 13 // * Redistributions in binary form must reproduce the above 14 // copyright notice, this list of conditions and the following disclaimer 15 // in the documentation and/or other materials provided with the 16 // distribution. 17 // * Neither the name of Industrial Light & Magic nor the names of 18 // its contributors may be used to endorse or promote products derived 19 // from this software without specific prior written permission. 20 // 21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 // 33 /////////////////////////////////////////////////////////////////////////// 34 35 36 37 #ifndef INCLUDED_IMATHQUAT_H 38 #define INCLUDED_IMATHQUAT_H 39 40 //---------------------------------------------------------------------- 41 // 42 // template class Quat<T> 43 // 44 // "Quaternions came from Hamilton ... and have been an unmixed 45 // evil to those who have touched them in any way. Vector is a 46 // useless survival ... and has never been of the slightest use 47 // to any creature." 48 // 49 // - Lord Kelvin 50 // 51 // This class implements the quaternion numerical type -- you 52 // will probably want to use this class to represent orientations 53 // in R3 and to convert between various euler angle reps. You 54 // should probably use Imath::Euler<> for that. 55 // 56 //---------------------------------------------------------------------- 57 58 #include "ImathExc.h" 59 #include "ImathMatrix.h" 60 61 #include <iostream> 62 63 namespace Imath { 64 65 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER 66 // Disable MS VC++ warnings about conversion from double to float 67 #pragma warning(disable:4244) 68 #endif 69 70 template <class T> 71 class Quat 72 { 73 public: 74 75 T r; // real part 76 Vec3<T> v; // imaginary vector 77 78 79 //----------------------------------------------------- 80 // Constructors - default constructor is identity quat 81 //----------------------------------------------------- 82 83 Quat (); 84 85 template <class S> 86 Quat (const Quat<S> &q); 87 88 Quat (T s, T i, T j, T k); 89 90 Quat (T s, Vec3<T> d); 91 92 static Quat<T> identity (); 93 94 95 //------------------------------------------------- 96 // Basic Algebra - Operators and Methods 97 // The operator return values are *NOT* normalized 98 // 99 // operator^ and euclideanInnnerProduct() both 100 // implement the 4D dot product 101 // 102 // operator/ uses the inverse() quaternion 103 // 104 // operator~ is conjugate -- if (S+V) is quat then 105 // the conjugate (S+V)* == (S-V) 106 // 107 // some operators (*,/,*=,/=) treat the quat as 108 // a 4D vector when one of the operands is scalar 109 //------------------------------------------------- 110 111 const Quat<T> & operator = (const Quat<T> &q); 112 const Quat<T> & operator *= (const Quat<T> &q); 113 const Quat<T> & operator *= (T t); 114 const Quat<T> & operator /= (const Quat<T> &q); 115 const Quat<T> & operator /= (T t); 116 const Quat<T> & operator += (const Quat<T> &q); 117 const Quat<T> & operator -= (const Quat<T> &q); 118 T & operator [] (int index); // as 4D vector 119 T operator [] (int index) const; 120 121 template <class S> bool operator == (const Quat<S> &q) const; 122 template <class S> bool operator != (const Quat<S> &q) const; 123 124 Quat<T> & invert (); // this -> 1 / this 125 Quat<T> inverse () const; 126 Quat<T> & normalize (); // returns this 127 Quat<T> normalized () const; 128 T length () const; // in R4 129 Vec3<T> rotateVector(const Vec3<T> &original) const; 130 T euclideanInnerProduct(const Quat<T> &q) const; 131 132 //----------------------- 133 // Rotation conversion 134 //----------------------- 135 136 Quat<T> & setAxisAngle (const Vec3<T> &axis, T radians); 137 138 Quat<T> & setRotation (const Vec3<T> &fromDirection, 139 const Vec3<T> &toDirection); 140 141 T angle () const; 142 Vec3<T> axis () const; 143 144 Matrix33<T> toMatrix33 () const; 145 Matrix44<T> toMatrix44 () const; 146 147 Quat<T> log () const; 148 Quat<T> exp () const; 149 150 151 private: 152 153 void setRotationInternal (const Vec3<T> &f0, 154 const Vec3<T> &t0, 155 Quat<T> &q); 156 }; 157 158 159 template<class T> 160 Quat<T> slerp (const Quat<T> &q1, const Quat<T> &q2, T t); 161 162 template<class T> 163 Quat<T> slerpShortestArc 164 (const Quat<T> &q1, const Quat<T> &q2, T t); 165 166 167 template<class T> 168 Quat<T> squad (const Quat<T> &q1, const Quat<T> &q2, 169 const Quat<T> &qa, const Quat<T> &qb, T t); 170 171 template<class T> 172 void intermediate (const Quat<T> &q0, const Quat<T> &q1, 173 const Quat<T> &q2, const Quat<T> &q3, 174 Quat<T> &qa, Quat<T> &qb); 175 176 template<class T> 177 Matrix33<T> operator * (const Matrix33<T> &M, const Quat<T> &q); 178 179 template<class T> 180 Matrix33<T> operator * (const Quat<T> &q, const Matrix33<T> &M); 181 182 template<class T> 183 std::ostream & operator << (std::ostream &o, const Quat<T> &q); 184 185 template<class T> 186 Quat<T> operator * (const Quat<T> &q1, const Quat<T> &q2); 187 188 template<class T> 189 Quat<T> operator / (const Quat<T> &q1, const Quat<T> &q2); 190 191 template<class T> 192 Quat<T> operator / (const Quat<T> &q, T t); 193 194 template<class T> 195 Quat<T> operator * (const Quat<T> &q, T t); 196 197 template<class T> 198 Quat<T> operator * (T t, const Quat<T> &q); 199 200 template<class T> 201 Quat<T> operator + (const Quat<T> &q1, const Quat<T> &q2); 202 203 template<class T> 204 Quat<T> operator - (const Quat<T> &q1, const Quat<T> &q2); 205 206 template<class T> 207 Quat<T> operator ~ (const Quat<T> &q); 208 209 template<class T> 210 Quat<T> operator - (const Quat<T> &q); 211 212 template<class T> 213 Vec3<T> operator * (const Vec3<T> &v, const Quat<T> &q); 214 215 216 //-------------------- 217 // Convenient typedefs 218 //-------------------- 219 220 typedef Quat<float> Quatf; 221 typedef Quat<double> Quatd; 222 223 224 //--------------- 225 // Implementation 226 //--------------- 227 228 template<class T> 229 inline 230 Quat<T>::Quat (): r (1), v (0, 0, 0) 231 { 232 // empty 233 } 234 235 236 template<class T> 237 template <class S> 238 inline 239 Quat<T>::Quat (const Quat<S> &q): r (q.r), v (q.v) 240 { 241 // empty 242 } 243 244 245 template<class T> 246 inline 247 Quat<T>::Quat (T s, T i, T j, T k): r (s), v (i, j, k) 248 { 249 // empty 250 } 251 252 253 template<class T> 254 inline 255 Quat<T>::Quat (T s, Vec3<T> d): r (s), v (d) 256 { 257 // empty 258 } 259 260 261 template<class T> 262 inline Quat<T> 263 Quat<T>::identity () 264 { 265 return Quat<T>(); 266 } 267 268 template<class T> 269 inline const Quat<T> & 270 Quat<T>::operator = (const Quat<T> &q) 271 { 272 r = q.r; 273 v = q.v; 274 return *this; 275 } 276 277 278 template<class T> 279 inline const Quat<T> & 280 Quat<T>::operator *= (const Quat<T> &q) 281 { 282 T rtmp = r * q.r - (v ^ q.v); 283 v = r * q.v + v * q.r + v % q.v; 284 r = rtmp; 285 return *this; 286 } 287 288 289 template<class T> 290 inline const Quat<T> & 291 Quat<T>::operator *= (T t) 292 { 293 r *= t; 294 v *= t; 295 return *this; 296 } 297 298 299 template<class T> 300 inline const Quat<T> & 301 Quat<T>::operator /= (const Quat<T> &q) 302 { 303 *this = *this * q.inverse(); 304 return *this; 305 } 306 307 308 template<class T> 309 inline const Quat<T> & 310 Quat<T>::operator /= (T t) 311 { 312 r /= t; 313 v /= t; 314 return *this; 315 } 316 317 318 template<class T> 319 inline const Quat<T> & 320 Quat<T>::operator += (const Quat<T> &q) 321 { 322 r += q.r; 323 v += q.v; 324 return *this; 325 } 326 327 328 template<class T> 329 inline const Quat<T> & 330 Quat<T>::operator -= (const Quat<T> &q) 331 { 332 r -= q.r; 333 v -= q.v; 334 return *this; 335 } 336 337 338 template<class T> 339 inline T & 340 Quat<T>::operator [] (int index) 341 { 342 return index ? v[index - 1] : r; 343 } 344 345 346 template<class T> 347 inline T 348 Quat<T>::operator [] (int index) const 349 { 350 return index ? v[index - 1] : r; 351 } 352 353 354 template <class T> 355 template <class S> 356 inline bool 357 Quat<T>::operator == (const Quat<S> &q) const 358 { 359 return r == q.r && v == q.v; 360 } 361 362 363 template <class T> 364 template <class S> 365 inline bool 366 Quat<T>::operator != (const Quat<S> &q) const 367 { 368 return r != q.r || v != q.v; 369 } 370 371 372 template<class T> 373 inline T 374 operator ^ (const Quat<T>& q1 ,const Quat<T>& q2) 375 { 376 return q1.r * q2.r + (q1.v ^ q2.v); 377 } 378 379 380 template <class T> 381 inline T 382 Quat<T>::length () const 383 { 384 return Math<T>::sqrt (r * r + (v ^ v)); 385 } 386 387 388 template <class T> 389 inline Quat<T> & 390 Quat<T>::normalize () 391 { 392 if (T l = length()) 393 { 394 r /= l; 395 v /= l; 396 } 397 else 398 { 399 r = 1; 400 v = Vec3<T> (0); 401 } 402 403 return *this; 404 } 405 406 407 template <class T> 408 inline Quat<T> 409 Quat<T>::normalized () const 410 { 411 if (T l = length()) 412 return Quat (r / l, v / l); 413 414 return Quat(); 415 } 416 417 418 template<class T> 419 inline Quat<T> 420 Quat<T>::inverse () const 421 { 422 // 423 // 1 Q* 424 // - = ---- where Q* is conjugate (operator~) 425 // Q Q* Q and (Q* Q) == Q ^ Q (4D dot) 426 // 427 428 T qdot = *this ^ *this; 429 return Quat (r / qdot, -v / qdot); 430 } 431 432 433 template<class T> 434 inline Quat<T> & 435 Quat<T>::invert () 436 { 437 T qdot = (*this) ^ (*this); 438 r /= qdot; 439 v = -v / qdot; 440 return *this; 441 } 442 443 444 template<class T> 445 inline Vec3<T> 446 Quat<T>::rotateVector(const Vec3<T>& original) const 447 { 448 // 449 // Given a vector p and a quaternion q (aka this), 450 // calculate p' = qpq* 451 // 452 // Assumes unit quaternions (because non-unit 453 // quaternions cannot be used to rotate vectors 454 // anyway). 455 // 456 457 Quat<T> vec (0, original); // temporarily promote grade of original 458 Quat<T> inv (*this); 459 inv.v *= -1; // unit multiplicative inverse 460 Quat<T> result = *this * vec * inv; 461 return result.v; 462 } 463 464 465 template<class T> 466 inline T 467 Quat<T>::euclideanInnerProduct (const Quat<T> &q) const 468 { 469 return r * q.r + v.x * q.v.x + v.y * q.v.y + v.z * q.v.z; 470 } 471 472 473 template<class T> 474 T 475 angle4D (const Quat<T> &q1, const Quat<T> &q2) 476 { 477 // 478 // Compute the angle between two quaternions, 479 // interpreting the quaternions as 4D vectors. 480 // 481 482 Quat<T> d = q1 - q2; 483 T lengthD = Math<T>::sqrt (d ^ d); 484 485 Quat<T> s = q1 + q2; 486 T lengthS = Math<T>::sqrt (s ^ s); 487 488 return 2 * Math<T>::atan2 (lengthD, lengthS); 489 } 490 491 492 template<class T> 493 Quat<T> 494 slerp (const Quat<T> &q1, const Quat<T> &q2, T t) 495 { 496 // 497 // Spherical linear interpolation. 498 // Assumes q1 and q2 are normalized and that q1 != -q2. 499 // 500 // This method does *not* interpolate along the shortest 501 // arc between q1 and q2. If you desire interpolation 502 // along the shortest arc, and q1^q2 is negative, then 503 // consider calling slerpShortestArc(), below, or flipping 504 // the second quaternion explicitly. 505 // 506 // The implementation of squad() depends on a slerp() 507 // that interpolates as is, without the automatic 508 // flipping. 509 // 510 // Don Hatch explains the method we use here on his 511 // web page, The Right Way to Calculate Stuff, at 512 // http://www.plunk.org/~hatch/rightway.php 513 // 514 515 T a = angle4D (q1, q2); 516 T s = 1 - t; 517 518 Quat<T> q = sinx_over_x (s * a) / sinx_over_x (a) * s * q1 + 519 sinx_over_x (t * a) / sinx_over_x (a) * t * q2; 520 521 return q.normalized(); 522 } 523 524 525 template<class T> 526 Quat<T> 527 slerpShortestArc (const Quat<T> &q1, const Quat<T> &q2, T t) 528 { 529 // 530 // Spherical linear interpolation along the shortest 531 // arc from q1 to either q2 or -q2, whichever is closer. 532 // Assumes q1 and q2 are unit quaternions. 533 // 534 535 if ((q1 ^ q2) >= 0) 536 return slerp (q1, q2, t); 537 else 538 return slerp (q1, -q2, t); 539 } 540 541 542 template<class T> 543 Quat<T> 544 spline (const Quat<T> &q0, const Quat<T> &q1, 545 const Quat<T> &q2, const Quat<T> &q3, 546 T t) 547 { 548 // 549 // Spherical Cubic Spline Interpolation - 550 // from Advanced Animation and Rendering 551 // Techniques by Watt and Watt, Page 366: 552 // A spherical curve is constructed using three 553 // spherical linear interpolations of a quadrangle 554 // of unit quaternions: q1, qa, qb, q2. 555 // Given a set of quaternion keys: q0, q1, q2, q3, 556 // this routine does the interpolation between 557 // q1 and q2 by constructing two intermediate 558 // quaternions: qa and qb. The qa and qb are 559 // computed by the intermediate function to 560 // guarantee the continuity of tangents across 561 // adjacent cubic segments. The qa represents in-tangent 562 // for q1 and the qb represents the out-tangent for q2. 563 // 564 // The q1 q2 is the cubic segment being interpolated. 565 // The q0 is from the previous adjacent segment and q3 is 566 // from the next adjacent segment. The q0 and q3 are used 567 // in computing qa and qb. 568 // 569 570 Quat<T> qa = intermediate (q0, q1, q2); 571 Quat<T> qb = intermediate (q1, q2, q3); 572 Quat<T> result = squad (q1, qa, qb, q2, t); 573 574 return result; 575 } 576 577 578 template<class T> 579 Quat<T> 580 squad (const Quat<T> &q1, const Quat<T> &qa, 581 const Quat<T> &qb, const Quat<T> &q2, 582 T t) 583 { 584 // 585 // Spherical Quadrangle Interpolation - 586 // from Advanced Animation and Rendering 587 // Techniques by Watt and Watt, Page 366: 588 // It constructs a spherical cubic interpolation as 589 // a series of three spherical linear interpolations 590 // of a quadrangle of unit quaternions. 591 // 592 593 Quat<T> r1 = slerp (q1, q2, t); 594 Quat<T> r2 = slerp (qa, qb, t); 595 Quat<T> result = slerp (r1, r2, 2 * t * (1 - t)); 596 597 return result; 598 } 599 600 601 template<class T> 602 Quat<T> 603 intermediate (const Quat<T> &q0, const Quat<T> &q1, const Quat<T> &q2) 604 { 605 // 606 // From advanced Animation and Rendering 607 // Techniques by Watt and Watt, Page 366: 608 // computing the inner quadrangle 609 // points (qa and qb) to guarantee tangent 610 // continuity. 611 // 612 613 Quat<T> q1inv = q1.inverse(); 614 Quat<T> c1 = q1inv * q2; 615 Quat<T> c2 = q1inv * q0; 616 Quat<T> c3 = (T) (-0.25) * (c2.log() + c1.log()); 617 Quat<T> qa = q1 * c3.exp(); 618 qa.normalize(); 619 return qa; 620 } 621 622 623 template <class T> 624 inline Quat<T> 625 Quat<T>::log () const 626 { 627 // 628 // For unit quaternion, from Advanced Animation and 629 // Rendering Techniques by Watt and Watt, Page 366: 630 // 631 632 T theta = Math<T>::acos (std::min (r, (T) 1.0)); 633 634 if (theta == 0) 635 return Quat<T> (0, v); 636 637 T sintheta = Math<T>::sin (theta); 638 639 T k; 640 if (abs (sintheta) < 1 && abs (theta) >= limits<T>::max() * abs (sintheta)) 641 k = 1; 642 else 643 k = theta / sintheta; 644 645 return Quat<T> ((T) 0, v.x * k, v.y * k, v.z * k); 646 } 647 648 649 template <class T> 650 inline Quat<T> 651 Quat<T>::exp () const 652 { 653 // 654 // For pure quaternion (zero scalar part): 655 // from Advanced Animation and Rendering 656 // Techniques by Watt and Watt, Page 366: 657 // 658 659 T theta = v.length(); 660 T sintheta = Math<T>::sin (theta); 661 662 T k; 663 if (abs (theta) < 1 && abs (sintheta) >= limits<T>::max() * abs (theta)) 664 k = 1; 665 else 666 k = sintheta / theta; 667 668 T costheta = Math<T>::cos (theta); 669 670 return Quat<T> (costheta, v.x * k, v.y * k, v.z * k); 671 } 672 673 674 template <class T> 675 inline T 676 Quat<T>::angle () const 677 { 678 return 2 * Math<T>::atan2 (v.length(), r); 679 } 680 681 682 template <class T> 683 inline Vec3<T> 684 Quat<T>::axis () const 685 { 686 return v.normalized(); 687 } 688 689 690 template <class T> 691 inline Quat<T> & 692 Quat<T>::setAxisAngle (const Vec3<T> &axis, T radians) 693 { 694 r = Math<T>::cos (radians / 2); 695 v = axis.normalized() * Math<T>::sin (radians / 2); 696 return *this; 697 } 698 699 700 template <class T> 701 Quat<T> & 702 Quat<T>::setRotation (const Vec3<T> &from, const Vec3<T> &to) 703 { 704 // 705 // Create a quaternion that rotates vector from into vector to, 706 // such that the rotation is around an axis that is the cross 707 // product of from and to. 708 // 709 // This function calls function setRotationInternal(), which is 710 // numerically accurate only for rotation angles that are not much 711 // greater than pi/2. In order to achieve good accuracy for angles 712 // greater than pi/2, we split large angles in half, and rotate in 713 // two steps. 714 // 715 716 // 717 // Normalize from and to, yielding f0 and t0. 718 // 719 720 Vec3<T> f0 = from.normalized(); 721 Vec3<T> t0 = to.normalized(); 722 723 if ((f0 ^ t0) >= 0) 724 { 725 // 726 // The rotation angle is less than or equal to pi/2. 727 // 728 729 setRotationInternal (f0, t0, *this); 730 } 731 else 732 { 733 // 734 // The angle is greater than pi/2. After computing h0, 735 // which is halfway between f0 and t0, we rotate first 736 // from f0 to h0, then from h0 to t0. 737 // 738 739 Vec3<T> h0 = (f0 + t0).normalized(); 740 741 if ((h0 ^ h0) != 0) 742 { 743 setRotationInternal (f0, h0, *this); 744 745 Quat<T> q; 746 setRotationInternal (h0, t0, q); 747 748 *this *= q; 749 } 750 else 751 { 752 // 753 // f0 and t0 point in exactly opposite directions. 754 // Pick an arbitrary axis that is orthogonal to f0, 755 // and rotate by pi. 756 // 757 758 r = T (0); 759 760 Vec3<T> f02 = f0 * f0; 761 762 if (f02.x <= f02.y && f02.x <= f02.z) 763 v = (f0 % Vec3<T> (1, 0, 0)).normalized(); 764 else if (f02.y <= f02.z) 765 v = (f0 % Vec3<T> (0, 1, 0)).normalized(); 766 else 767 v = (f0 % Vec3<T> (0, 0, 1)).normalized(); 768 } 769 } 770 771 return *this; 772 } 773 774 775 template <class T> 776 void 777 Quat<T>::setRotationInternal (const Vec3<T> &f0, const Vec3<T> &t0, Quat<T> &q) 778 { 779 // 780 // The following is equivalent to setAxisAngle(n,2*phi), 781 // where the rotation axis, n, is orthogonal to the f0 and 782 // t0 vectors, and 2*phi is the angle between f0 and t0. 783 // 784 // This function is called by setRotation(), above; it assumes 785 // that f0 and t0 are normalized and that the angle between 786 // them is not much greater than pi/2. This function becomes 787 // numerically inaccurate if f0 and t0 point into nearly 788 // opposite directions. 789 // 790 791 // 792 // Find a normalized vector, h0, that is halfway between f0 and t0. 793 // The angle between f0 and h0 is phi. 794 // 795 796 Vec3<T> h0 = (f0 + t0).normalized(); 797 798 // 799 // Store the rotation axis and rotation angle. 800 // 801 802 q.r = f0 ^ h0; // f0 ^ h0 == cos (phi) 803 q.v = f0 % h0; // (f0 % h0).length() == sin (phi) 804 } 805 806 807 template<class T> 808 Matrix33<T> 809 Quat<T>::toMatrix33() const 810 { 811 return Matrix33<T> (1 - 2 * (v.y * v.y + v.z * v.z), 812 2 * (v.x * v.y + v.z * r), 813 2 * (v.z * v.x - v.y * r), 814 815 2 * (v.x * v.y - v.z * r), 816 1 - 2 * (v.z * v.z + v.x * v.x), 817 2 * (v.y * v.z + v.x * r), 818 819 2 * (v.z * v.x + v.y * r), 820 2 * (v.y * v.z - v.x * r), 821 1 - 2 * (v.y * v.y + v.x * v.x)); 822 } 823 824 template<class T> 825 Matrix44<T> 826 Quat<T>::toMatrix44() const 827 { 828 return Matrix44<T> (1 - 2 * (v.y * v.y + v.z * v.z), 829 2 * (v.x * v.y + v.z * r), 830 2 * (v.z * v.x - v.y * r), 831 0, 832 2 * (v.x * v.y - v.z * r), 833 1 - 2 * (v.z * v.z + v.x * v.x), 834 2 * (v.y * v.z + v.x * r), 835 0, 836 2 * (v.z * v.x + v.y * r), 837 2 * (v.y * v.z - v.x * r), 838 1 - 2 * (v.y * v.y + v.x * v.x), 839 0, 840 0, 841 0, 842 0, 843 1); 844 } 845 846 847 template<class T> 848 inline Matrix33<T> 849 operator * (const Matrix33<T> &M, const Quat<T> &q) 850 { 851 return M * q.toMatrix33(); 852 } 853 854 855 template<class T> 856 inline Matrix33<T> 857 operator * (const Quat<T> &q, const Matrix33<T> &M) 858 { 859 return q.toMatrix33() * M; 860 } 861 862 863 template<class T> 864 std::ostream & 865 operator << (std::ostream &o, const Quat<T> &q) 866 { 867 return o << "(" << q.r 868 << " " << q.v.x 869 << " " << q.v.y 870 << " " << q.v.z 871 << ")"; 872 } 873 874 875 template<class T> 876 inline Quat<T> 877 operator * (const Quat<T> &q1, const Quat<T> &q2) 878 { 879 return Quat<T> (q1.r * q2.r - (q1.v ^ q2.v), 880 q1.r * q2.v + q1.v * q2.r + q1.v % q2.v); 881 } 882 883 884 template<class T> 885 inline Quat<T> 886 operator / (const Quat<T> &q1, const Quat<T> &q2) 887 { 888 return q1 * q2.inverse(); 889 } 890 891 892 template<class T> 893 inline Quat<T> 894 operator / (const Quat<T> &q, T t) 895 { 896 return Quat<T> (q.r / t, q.v / t); 897 } 898 899 900 template<class T> 901 inline Quat<T> 902 operator * (const Quat<T> &q, T t) 903 { 904 return Quat<T> (q.r * t, q.v * t); 905 } 906 907 908 template<class T> 909 inline Quat<T> 910 operator * (T t, const Quat<T> &q) 911 { 912 return Quat<T> (q.r * t, q.v * t); 913 } 914 915 916 template<class T> 917 inline Quat<T> 918 operator + (const Quat<T> &q1, const Quat<T> &q2) 919 { 920 return Quat<T> (q1.r + q2.r, q1.v + q2.v); 921 } 922 923 924 template<class T> 925 inline Quat<T> 926 operator - (const Quat<T> &q1, const Quat<T> &q2) 927 { 928 return Quat<T> (q1.r - q2.r, q1.v - q2.v); 929 } 930 931 932 template<class T> 933 inline Quat<T> 934 operator ~ (const Quat<T> &q) 935 { 936 return Quat<T> (q.r, -q.v); 937 } 938 939 940 template<class T> 941 inline Quat<T> 942 operator - (const Quat<T> &q) 943 { 944 return Quat<T> (-q.r, -q.v); 945 } 946 947 948 template<class T> 949 inline Vec3<T> 950 operator * (const Vec3<T> &v, const Quat<T> &q) 951 { 952 Vec3<T> a = q.v % v; 953 Vec3<T> b = q.v % a; 954 return v + T (2) * (q.r * a + b); 955 } 956 957 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER 958 #pragma warning(default:4244) 959 #endif 960 961 } // namespace Imath 962 963 #endif 964