| | 478 | /*! Returns the 1-norm of the upper left 3x3 part of this matrix. |
|---|
| | 479 | The 1-norm is also known as maximum absolute column sum norm. |
|---|
| | 480 | |
|---|
| | 481 | \return 1-norm of \a matrix. |
|---|
| | 482 | */ |
|---|
| | 483 | template <class ValueTypeT> |
|---|
| | 484 | inline typename TransformationMatrix<ValueTypeT>::ValueType |
|---|
| | 485 | TransformationMatrix<ValueTypeT>::norm1_3x3(void) const |
|---|
| | 486 | { |
|---|
| | 487 | ValueType max; |
|---|
| | 488 | ValueType t; |
|---|
| | 489 | |
|---|
| | 490 | max = osgAbs(_matrix[0][0]) + |
|---|
| | 491 | osgAbs(_matrix[0][1]) + |
|---|
| | 492 | osgAbs(_matrix[0][2]); |
|---|
| | 493 | |
|---|
| | 494 | if((t = osgAbs(_matrix[1][0]) + |
|---|
| | 495 | osgAbs(_matrix[1][1]) + |
|---|
| | 496 | osgAbs(_matrix[1][2]) ) > max) |
|---|
| | 497 | { |
|---|
| | 498 | max = t; |
|---|
| | 499 | } |
|---|
| | 500 | |
|---|
| | 501 | if((t = osgAbs(_matrix[2][0]) + |
|---|
| | 502 | osgAbs(_matrix[2][1]) + |
|---|
| | 503 | osgAbs(_matrix[2][2]) ) > max) |
|---|
| | 504 | { |
|---|
| | 505 | max = t; |
|---|
| | 506 | } |
|---|
| | 507 | |
|---|
| | 508 | return max; |
|---|
| | 509 | } |
|---|
| | 510 | |
|---|
| | 511 | /*! Returns the infinity-norm of the upper left 3x3 part of this matrix. |
|---|
| | 512 | The infinity-norm is also known as maximum absolute row sum norm. |
|---|
| | 513 | |
|---|
| | 514 | \return infinity-norm of \a matrix. |
|---|
| | 515 | */ |
|---|
| | 516 | template <class ValueTypeT> |
|---|
| | 517 | inline typename TransformationMatrix<ValueTypeT>::ValueType |
|---|
| | 518 | TransformationMatrix<ValueTypeT>::normInf_3x3(void) const |
|---|
| | 519 | { |
|---|
| | 520 | ValueType max; |
|---|
| | 521 | ValueType t; |
|---|
| | 522 | |
|---|
| | 523 | max = osgAbs(_matrix[0][0]) + |
|---|
| | 524 | osgAbs(_matrix[1][0]) + |
|---|
| | 525 | osgAbs(_matrix[2][0]); |
|---|
| | 526 | |
|---|
| | 527 | if((t = osgAbs(_matrix[0][1]) + |
|---|
| | 528 | osgAbs(_matrix[1][1]) + |
|---|
| | 529 | osgAbs(_matrix[2][1]) ) > max) |
|---|
| | 530 | { |
|---|
| | 531 | max = t; |
|---|
| | 532 | } |
|---|
| | 533 | |
|---|
| | 534 | if((t = osgAbs(_matrix[0][2]) + |
|---|
| | 535 | osgAbs(_matrix[1][2]) + |
|---|
| | 536 | osgAbs(_matrix[2][2]) ) > max) |
|---|
| | 537 | { |
|---|
| | 538 | max = t; |
|---|
| | 539 | } |
|---|
| | 540 | |
|---|
| | 541 | return max; |
|---|
| | 542 | } |
|---|
| | 543 | |
|---|
| | 544 | /*! Computes the transpose of the adjoint of the upper left 3x3 part of |
|---|
| | 545 | this matrix and stores it in \a result. |
|---|
| | 546 | This is used in polarDecomposition. |
|---|
| | 547 | |
|---|
| | 548 | \param[out] Transpose of adjoint. |
|---|
| | 549 | */ |
|---|
| | 550 | template <class ValueTypeT> |
|---|
| | 551 | inline void |
|---|
| | 552 | TransformationMatrix<ValueTypeT>::adjointT_3x3( |
|---|
| | 553 | TransformationMatrix<ValueTypeT> &result) const |
|---|
| | 554 | { |
|---|
| | 555 | result[0][0] = _matrix[1][1] * _matrix[2][2] - _matrix[2][1] * _matrix[1][2]; |
|---|
| | 556 | result[1][0] = _matrix[2][1] * _matrix[0][2] - _matrix[0][1] * _matrix[2][2]; |
|---|
| | 557 | result[2][0] = _matrix[0][1] * _matrix[1][2] - _matrix[1][1] * _matrix[0][2]; |
|---|
| | 558 | |
|---|
| | 559 | result[0][1] = _matrix[1][2] * _matrix[2][0] - _matrix[2][2] * _matrix[1][0]; |
|---|
| | 560 | result[1][1] = _matrix[2][2] * _matrix[0][0] - _matrix[0][2] * _matrix[2][0]; |
|---|
| | 561 | result[2][1] = _matrix[0][2] * _matrix[1][0] - _matrix[1][2] * _matrix[0][0]; |
|---|
| | 562 | |
|---|
| | 563 | result[0][2] = _matrix[1][0] * _matrix[2][1] - _matrix[2][0] * _matrix[1][1]; |
|---|
| | 564 | result[1][2] = _matrix[2][0] * _matrix[0][1] - _matrix[0][0] * _matrix[2][1]; |
|---|
| | 565 | result[2][2] = _matrix[0][0] * _matrix[1][1] - _matrix[1][0] * _matrix[0][1]; |
|---|
| | 566 | } |
|---|
| | 567 | |
|---|
| | 568 | /*! Computes the decomposition M = QS of a non-singular, affine matrix \a M |
|---|
| | 569 | (\c this) into an orthogonal matrix \a Q (basically a rotation, but may |
|---|
| | 570 | also reflect) and a symmetric positive semi-definite matrix \a S (basically |
|---|
| | 571 | a non-uniform scaling in \em some orthonormal basis). |
|---|
| | 572 | The sign of the determinant of Q can be used to distinguish the case where |
|---|
| | 573 | \a Q contains a reflection (det(Q) < 0). |
|---|
| | 574 | |
|---|
| | 575 | \param[out] Q Rotation and reflection component. |
|---|
| | 576 | \param[out] S Scaling component. |
|---|
| | 577 | \param[out] det Determinant of Q. |
|---|
| | 578 | |
|---|
| | 579 | Code taken from Graphics Gems IV article III.4 "Polar Matrix Decomposition". |
|---|
| | 580 | */ |
|---|
| | 581 | template <class ValueTypeT> |
|---|
| | 582 | inline void |
|---|
| | 583 | TransformationMatrix<ValueTypeT>::polarDecompose( |
|---|
| | 584 | TransformationMatrix &Q, |
|---|
| | 585 | TransformationMatrix &S, |
|---|
| | 586 | ValueType &det) const |
|---|
| | 587 | { |
|---|
| | 588 | ValueType const TOL = 1.0e-6; |
|---|
| | 589 | |
|---|
| | 590 | TransformationMatrix const &M = *this; |
|---|
| | 591 | TransformationMatrix Mk; |
|---|
| | 592 | TransformationMatrix Ek; |
|---|
| | 593 | TransformationMatrix MkAdjT; |
|---|
| | 594 | |
|---|
| | 595 | Mk.transposeFrom(M); |
|---|
| | 596 | |
|---|
| | 597 | ValueType Mk_one = Mk.norm1_3x3 (); |
|---|
| | 598 | ValueType Mk_inf = Mk.normInf_3x3(); |
|---|
| | 599 | |
|---|
| | 600 | ValueType MkAdjT_one; |
|---|
| | 601 | ValueType MkAdjT_inf; |
|---|
| | 602 | |
|---|
| | 603 | ValueType Ek_one; |
|---|
| | 604 | ValueType Mk_det; |
|---|
| | 605 | |
|---|
| | 606 | do |
|---|
| | 607 | { |
|---|
| | 608 | // compute transpose of adjoint |
|---|
| | 609 | Mk.adjointT_3x3(MkAdjT); |
|---|
| | 610 | |
|---|
| | 611 | // Mk_det = det(Mk) -- computed from the adjoint |
|---|
| | 612 | Mk_det = Mk[0][0] * MkAdjT[0][0] + |
|---|
| | 613 | Mk[1][0] * MkAdjT[1][0] + |
|---|
| | 614 | Mk[2][0] * MkAdjT[2][0]; |
|---|
| | 615 | |
|---|
| | 616 | // should this be a close to zero test ? |
|---|
| | 617 | if(Mk_det == TypeTraits<ValueType>::getZeroElement()) |
|---|
| | 618 | { |
|---|
| | 619 | FWARNING(("polarDecompose: Mk_det == 0.0\n")); |
|---|
| | 620 | break; |
|---|
| | 621 | } |
|---|
| | 622 | |
|---|
| | 623 | MkAdjT_one = MkAdjT.norm1_3x3 (); |
|---|
| | 624 | MkAdjT_inf = MkAdjT.normInf_3x3(); |
|---|
| | 625 | |
|---|
| | 626 | // compute update factors |
|---|
| | 627 | ValueType gamma = |
|---|
| | 628 | osgSqrt( |
|---|
| | 629 | osgSqrt((MkAdjT_one * MkAdjT_inf) / (Mk_one * Mk_inf)) / |
|---|
| | 630 | osgAbs(Mk_det)); |
|---|
| | 631 | |
|---|
| | 632 | ValueType g1 = 0.5 * gamma; |
|---|
| | 633 | ValueType g2 = 0.5 / (gamma * Mk_det); |
|---|
| | 634 | |
|---|
| | 635 | Ek = Mk; |
|---|
| | 636 | Mk.scale (g1 ); // this does: |
|---|
| | 637 | Mk.addScaled(MkAdjT, g2 ); // Mk = g1 * Mk + g2 * MkAdjT |
|---|
| | 638 | Ek.addScaled(Mk, -1.0); // Ek -= Mk; |
|---|
| | 639 | |
|---|
| | 640 | Ek_one = Ek.norm1_3x3 (); |
|---|
| | 641 | Mk_one = Mk.norm1_3x3 (); |
|---|
| | 642 | Mk_inf = Mk.normInf_3x3(); |
|---|
| | 643 | |
|---|
| | 644 | } while(Ek_one > (Mk_one * TOL)); |
|---|
| | 645 | |
|---|
| | 646 | Q = Mk; |
|---|
| | 647 | Q.transpose(); |
|---|
| | 648 | |
|---|
| | 649 | S = Mk; |
|---|
| | 650 | S.mult(M); |
|---|
| | 651 | |
|---|
| | 652 | for(UInt32 i = 0; i < 3; ++i) |
|---|
| | 653 | { |
|---|
| | 654 | for(UInt32 j = i; j < 3; ++j) |
|---|
| | 655 | { |
|---|
| | 656 | S[j][i] = S[i][j] = 0.5 * (S[j][i] + S[i][j]); |
|---|
| | 657 | } |
|---|
| | 658 | } |
|---|
| | 659 | |
|---|
| | 660 | det = Mk_det; |
|---|
| | 661 | } |
|---|
| | 662 | |
|---|
| | 663 | /*! Computes a spectral decomposition of a symmetric positive |
|---|
| | 664 | semi-definite matrix \a S (\c this) into a rotation matrix \a SO and |
|---|
| | 665 | a vector of scaling values \a k. |
|---|
| | 666 | The decomposition satisfies S = SO K SO^t, where K is the diagonal matrix |
|---|
| | 667 | of scaling factors. |
|---|
| | 668 | |
|---|
| | 669 | \param[out] SO Scale orientation rotation matrix. |
|---|
| | 670 | \param[out] k Scaling factors. |
|---|
| | 671 | |
|---|
| | 672 | Code taken from Graphics Gems IV article III.4 "Polar Matrix Decomposition". |
|---|
| | 673 | */ |
|---|
| | 674 | template <class ValueTypeT> |
|---|
| | 675 | inline void |
|---|
| | 676 | TransformationMatrix<ValueTypeT>::spectralDecompose( |
|---|
| | 677 | TransformationMatrix &SO, |
|---|
| | 678 | VectorType3f &k ) const |
|---|
| | 679 | { |
|---|
| | 680 | UInt32 const next[3] = {1, 2, 0}; |
|---|
| | 681 | UInt32 const maxIterations = 20; |
|---|
| | 682 | |
|---|
| | 683 | TransformationMatrix const &S = *this; |
|---|
| | 684 | |
|---|
| | 685 | ValueType diag[3]; |
|---|
| | 686 | ValueType offDiag[3]; |
|---|
| | 687 | |
|---|
| | 688 | diag[0] = S[0][0]; |
|---|
| | 689 | diag[1] = S[1][1]; |
|---|
| | 690 | diag[2] = S[2][2]; |
|---|
| | 691 | |
|---|
| | 692 | offDiag[0] = S[2][1]; |
|---|
| | 693 | offDiag[1] = S[0][2]; |
|---|
| | 694 | offDiag[2] = S[1][0]; |
|---|
| | 695 | |
|---|
| | 696 | for(UInt32 iter = 0; iter < maxIterations; ++iter) |
|---|
| | 697 | { |
|---|
| | 698 | ValueType sm = osgAbs(offDiag[0]) + osgAbs(offDiag[1]) + osgAbs(offDiag[2]); |
|---|
| | 699 | |
|---|
| | 700 | if(sm == TypeTraits<ValueType>::getZeroElement()) |
|---|
| | 701 | { |
|---|
| | 702 | break; |
|---|
| | 703 | } |
|---|
| | 704 | |
|---|
| | 705 | for(Int32 i = 2; i >= 0; --i) |
|---|
| | 706 | { |
|---|
| | 707 | UInt32 p = next[i]; |
|---|
| | 708 | UInt32 q = next[p]; |
|---|
| | 709 | |
|---|
| | 710 | ValueType absOffDiag = osgAbs(offDiag[i]); |
|---|
| | 711 | ValueType g = 100.0 * absOffDiag; |
|---|
| | 712 | |
|---|
| | 713 | if(absOffDiag > 0.0) |
|---|
| | 714 | { |
|---|
| | 715 | ValueType t; |
|---|
| | 716 | ValueType h = diag[q] - diag[p]; |
|---|
| | 717 | ValueType absh = osgAbs(h); |
|---|
| | 718 | |
|---|
| | 719 | if(absh + g == absh) |
|---|
| | 720 | { |
|---|
| | 721 | t = offDiag[i] / h; |
|---|
| | 722 | } |
|---|
| | 723 | else |
|---|
| | 724 | { |
|---|
| | 725 | ValueType theta = 0.5 * h / offDiag[i]; |
|---|
| | 726 | t = 1.0 / (osgAbs(theta) + osgSqrt(theta * theta + 1.0)); |
|---|
| | 727 | |
|---|
| | 728 | t = theta < 0.0 ? -t : t; |
|---|
| | 729 | } |
|---|
| | 730 | |
|---|
| | 731 | ValueType c = 1.0 / osgSqrt(t * t + 1.0); |
|---|
| | 732 | ValueType s = t * c; |
|---|
| | 733 | |
|---|
| | 734 | ValueType tau = s / (c + 1.0); |
|---|
| | 735 | ValueType ta = t * offDiag[i]; |
|---|
| | 736 | |
|---|
| | 737 | offDiag[i] = 0.0; |
|---|
| | 738 | |
|---|
| | 739 | diag[p] -= ta; |
|---|
| | 740 | diag[q] += ta; |
|---|
| | 741 | |
|---|
| | 742 | ValueType offDiagq = offDiag[q]; |
|---|
| | 743 | |
|---|
| | 744 | offDiag[q] -= s * (offDiag[p] + tau * offDiag[q]); |
|---|
| | 745 | offDiag[p] += s * (offDiagq - tau * offDiag[p]); |
|---|
| | 746 | |
|---|
| | 747 | for(Int32 j = 2; j >= 0; --j) |
|---|
| | 748 | { |
|---|
| | 749 | ValueType a = SO[p][j]; |
|---|
| | 750 | ValueType b = SO[q][j]; |
|---|
| | 751 | |
|---|
| | 752 | SO[p][j] -= s * (b + tau * a); |
|---|
| | 753 | SO[q][j] += s * (a - tau * b); |
|---|
| | 754 | } |
|---|
| | 755 | } |
|---|
| | 756 | } |
|---|
| | 757 | } |
|---|
| | 758 | |
|---|
| | 759 | k[0] = diag[0]; |
|---|
| | 760 | k[1] = diag[1]; |
|---|
| | 761 | k[2] = diag[2]; |
|---|
| | 762 | } |
|---|
| | 763 | |
|---|
| | 764 | /*! Computes the decomposition of the 4x4 affine matrix \a M (\c this) as |
|---|
| | 765 | M = T F R SO S SO^t, where T is a translation matrix, F is +/- I |
|---|
| | 766 | (a reflection), R is a rotation matrix, SO is a rotation matrix and S |
|---|
| | 767 | is a (nonuniform) scale matrix. |
|---|
| | 768 | The results of the decomposition are not returned as matrices but as more |
|---|
| | 769 | appropriate types. |
|---|
| | 770 | |
|---|
| | 771 | Code taken from Graphics Gems IV article III.4 "Polar Matrix Decomposition". |
|---|
| | 772 | Note: The "spectral axis adjustment" part, i.e. the "snuggle" function, |
|---|
| | 773 | is not implemented here. |
|---|
| | 774 | */ |
|---|
| | 775 | template <class ValueTypeT> |
|---|
| | 776 | inline void |
|---|
| | 777 | TransformationMatrix<ValueTypeT>::decompose( |
|---|
| | 778 | VectorType3f &t, |
|---|
| | 779 | ValueType &f, |
|---|
| | 780 | QuaternionType &r, |
|---|
| | 781 | QuaternionType &so, |
|---|
| | 782 | VectorType3f &s ) const |
|---|
| | 783 | { |
|---|
| | 784 | TransformationMatrix A = *this; |
|---|
| | 785 | TransformationMatrix Q; |
|---|
| | 786 | TransformationMatrix S; |
|---|
| | 787 | TransformationMatrix SO; |
|---|
| | 788 | ValueType det; |
|---|
| | 789 | |
|---|
| | 790 | t[0] = A[3][0]; |
|---|
| | 791 | t[1] = A[3][1]; |
|---|
| | 792 | t[2] = A[3][2]; |
|---|
| | 793 | |
|---|
| | 794 | A[3][0] = 0.0; |
|---|
| | 795 | A[3][1] = 0.0; |
|---|
| | 796 | A[3][2] = 0.0; |
|---|
| | 797 | |
|---|
| | 798 | A[0][3] = 0.0; |
|---|
| | 799 | A[1][3] = 0.0; |
|---|
| | 800 | A[2][3] = 0.0; |
|---|
| | 801 | |
|---|
| | 802 | A.polarDecompose(Q, S, det); |
|---|
| | 803 | |
|---|
| | 804 | if(det < 0.0) |
|---|
| | 805 | { |
|---|
| | 806 | Q.negate(); |
|---|
| | 807 | f = - 1.0; |
|---|
| | 808 | } |
|---|
| | 809 | else |
|---|
| | 810 | { |
|---|
| | 811 | f = 1.0; |
|---|
| | 812 | } |
|---|
| | 813 | |
|---|
| | 814 | r.setValue(Q); |
|---|
| | 815 | |
|---|
| | 816 | S.spectralDecompose(SO, s); |
|---|
| | 817 | |
|---|
| | 818 | so.setValue(SO); |
|---|
| | 819 | } |
|---|
| | 820 | |
|---|