Show
Ignore:
Timestamp:
01/21/08 16:07:56 (1 year ago)
Author:
cneumann
Message:

fixed: getTransform decomposes matrix into correct transformation

parts


The implementation of this functionality is from
Graphics Gems IV, article III.4 "Polar Matrix Decomposition".

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/Source/Base/Base/OSGMatrix.inl

    r785 r1040  
    476476} 
    477477 
     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 */ 
     483template <class ValueTypeT> 
     484inline 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 */ 
     516template <class ValueTypeT> 
     517inline 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 */ 
     550template <class ValueTypeT> 
     551inline 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 */ 
     581template <class ValueTypeT> 
     582inline 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 */ 
     674template <class ValueTypeT> 
     675inline 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 */ 
     775template <class ValueTypeT> 
     776inline 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 
    478821#ifdef __sgi 
    479822#pragma set woff 1424 
     
    10181361    QuaternionType &scaleOrientation) const 
    10191362{ 
     1363    ValueType            flip; 
    10201364    TransformationMatrix so; 
    10211365    TransformationMatrix rot; 
    10221366    TransformationMatrix proj; 
    10231367 
    1024     this->factor(so, scaleFactor, rot, translation, proj); 
    1025  
    1026     so.transpose(); 
    1027     scaleOrientation.setValue(so); 
    1028  
    1029     // gives us transpose of correct answer. 
    1030     rotation.setValue(rot); 
    1031  
     1368    this->decompose(translation, flip, rotation, scaleOrientation, scaleFactor); 
    10321369} 
    10331370 
     
    10361373    and t is a translation. Any projection information is returned 
    10371374    in proj. 
     1375     
     1376    \bug This function seems to be BROKEN. 
    10381377*/ 
    10391378