K3dQuaternion.cpp

Go to the documentation of this file.
00001 
00012 /***************************************************************************
00013  *   Copyright (C) 2007 by Jan Koci   *
00014  *   honza.koci@email.cz   *
00015  *   http://kengine.sourceforge.net/tutorial/
00016  *                                                                         *
00017  *   This program is free software; you can redistribute it and/or modify  *
00018  *   it under the terms of the GNU General Public License as published by  *
00019  *   the Free Software Foundation; either version 2 of the License, or     *
00020  *   (at your option) any later version.                                   *
00021  *                                                                         *
00022  *   This program is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00025  *   GNU General Public License for more details.                          *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU General Public License     *
00028  *   along with this program; if not, write to the                         *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00031  ***************************************************************************/
00032 
00033 
00034 #include "K3dQuaternion.h"
00035 
00036 #define     EQUIVALENT(a,b)     (((a < b + K3dMath::EPSILON) && (a > b - K3dMath::EPSILON)) ? true : false)
00037 
00038 
00039 
00040 
00041 
00042 K3dQuaternion::K3dQuaternion ( void )
00043 {
00044 }
00045 
00046 K3dQuaternion::~K3dQuaternion ( void )
00047 {
00048 }
00049 
00050 K3dQuaternion::K3dQuaternion ( float fX, float fY, float fZ, float fW )
00051 {
00052         m_afTuple[0] = fX;
00053         m_afTuple[1] = fY;
00054         m_afTuple[2] = fZ;
00055         m_afTuple[3] = fW;
00056 }
00057 
00058 K3dQuaternion::K3dQuaternion ( K3dVector4 kVec4 )
00059 {
00060         m_afTuple[0] = kVec4[0];
00061         m_afTuple[1] = kVec4[1];
00062         m_afTuple[2] = kVec4[2];
00063         m_afTuple[3] = kVec4[3];
00064 }
00065 
00066 K3dQuaternion::K3dQuaternion ( float afVector[4] )
00067 {
00068         for ( int i=0; i<4; i++ )
00069         {
00070                 m_afTuple[i] = afVector[i];
00071         }
00072 }
00073 
00074 K3dQuaternion::K3dQuaternion ( K3dQuaternion& rkQ )
00075 {
00076         memcpy ( m_afTuple,rkQ.m_afTuple,4*sizeof ( float ) );
00077 }
00078 
00079 K3dQuaternion::K3dQuaternion ( K3dMatrix& rkRot )
00080 {
00081         FromRotationMatrix ( rkRot );
00082 }
00083 
00084 K3dQuaternion::K3dQuaternion ( K3dVector3& rkAxis, float fAngle )
00085 {
00086         FromAxisAngle ( rkAxis,fAngle );
00087 }
00088 
00089 K3dQuaternion::K3dQuaternion ( K3dVector3 akRotColumn[3] )
00090 {
00091         FromRotationMatrix ( akRotColumn );
00092 }
00093 
00094 K3dQuaternion::operator const float* () const
00095 {
00096         return m_afTuple;
00097 }
00098 
00099 K3dQuaternion::operator float* ()
00100 {
00101         return m_afTuple;
00102 }
00103 
00104 float& K3dQuaternion::operator[] ( int i )
00105 {
00106         if ( ! ( 0 <= i && i < 4 ) )
00107         {
00108                 cerr << "float K3dQuaternion::operator[] (int i) const -- Error index" << endl;
00109         }
00110         return m_afTuple[i];
00111 }
00112 
00113 float K3dQuaternion::W () const
00114 {
00115         return m_afTuple[3];
00116 }
00117 
00118 float& K3dQuaternion::W ()
00119 {
00120         return m_afTuple[3];
00121 }
00122 
00123 float K3dQuaternion::X () const
00124 {
00125         return m_afTuple[0];
00126 }
00127 
00128 float& K3dQuaternion::X ()
00129 {
00130         return m_afTuple[0];
00131 }
00132 
00133 float K3dQuaternion::Y () const
00134 {
00135         return m_afTuple[1];
00136 }
00137 
00138 float& K3dQuaternion::Y ()
00139 {
00140         return m_afTuple[1];
00141 }
00142 
00143 float K3dQuaternion::Z () const
00144 {
00145         return m_afTuple[2];
00146 }
00147 
00148 float& K3dQuaternion::Z ()
00149 {
00150         return m_afTuple[2];
00151 }
00152 
00153 K3dQuaternion& K3dQuaternion::operator= ( K3dQuaternion& rkQ )
00154 {
00155         memcpy ( m_afTuple,rkQ.m_afTuple,4*sizeof ( float ) );
00156         return *this;
00157 }
00158 
00159 bool K3dQuaternion::operator== ( K3dQuaternion& rkQ )
00160 {
00161         for ( int i = 0; i < 4; i++ )
00162         {
00163                 if ( m_afTuple[i] != rkQ.m_afTuple[i] )
00164                         return false;
00165         }
00166         return true;
00167 }
00168 
00169 bool K3dQuaternion::operator!= ( K3dQuaternion& rkQ )
00170 {
00171         return !operator== ( rkQ );
00172 }
00173 
00174 int K3dQuaternion::CompareArrays ( K3dQuaternion& rkQ )
00175 {
00176         for ( int i = 0; i < 4; i++ )
00177         {
00178                 unsigned int uiTest0 = * ( unsigned int* ) &m_afTuple[i];
00179                 unsigned int uiTest1 = * ( unsigned int* ) &rkQ.m_afTuple[i];
00180                 if ( uiTest0 < uiTest1 )
00181                         return -1;
00182                 if ( uiTest0 > uiTest1 )
00183                         return +1;
00184         }
00185         return 0;
00186 }
00187 
00188 bool K3dQuaternion::operator< ( K3dQuaternion& rkQ )
00189 {
00190         return CompareArrays ( rkQ ) < 0;
00191 }
00192 
00193 bool K3dQuaternion::operator<= ( K3dQuaternion& rkQ )
00194 {
00195         return CompareArrays ( rkQ ) <= 0;
00196 }
00197 
00198 bool K3dQuaternion::operator> ( K3dQuaternion& rkQ )
00199 {
00200         return CompareArrays ( rkQ ) > 0;
00201 }
00202 
00203 bool K3dQuaternion::operator>= ( K3dQuaternion& rkQ )
00204 {
00205         return CompareArrays ( rkQ ) >= 0;
00206 }
00207 
00208 K3dQuaternion& K3dQuaternion::operator+ ( K3dQuaternion& rkQ )
00209 {
00210         for ( int i = 0; i < 4; i++ )
00211                 m_afTuple[i] = m_afTuple[i] + rkQ.m_afTuple[i];
00212         return *this;
00213 }
00214 
00215 K3dQuaternion& K3dQuaternion::operator- ( K3dQuaternion& rkQ )
00216 {
00217         for ( int i = 0; i < 4; i++ )
00218                 m_afTuple[i] = m_afTuple[i] - rkQ.m_afTuple[i];
00219         return *this;
00220 }
00221 
00223 K3dQuaternion& K3dQuaternion::operator* ( K3dQuaternion& rkQ )
00224 {
00225         K3dQuaternion kProd;
00226 
00227         kProd.m_afTuple[0] =
00228             m_afTuple[0]*rkQ.m_afTuple[0] -
00229             m_afTuple[1]*rkQ.m_afTuple[1] -
00230             m_afTuple[2]*rkQ.m_afTuple[2] -
00231             m_afTuple[3]*rkQ.m_afTuple[3];
00232 
00233         kProd.m_afTuple[1] =
00234             m_afTuple[0]*rkQ.m_afTuple[1] +
00235             m_afTuple[1]*rkQ.m_afTuple[0] +
00236             m_afTuple[2]*rkQ.m_afTuple[3] -
00237             m_afTuple[3]*rkQ.m_afTuple[2];
00238 
00239         kProd.m_afTuple[2] =
00240             m_afTuple[0]*rkQ.m_afTuple[2] +
00241             m_afTuple[2]*rkQ.m_afTuple[0] +
00242             m_afTuple[3]*rkQ.m_afTuple[1] -
00243             m_afTuple[1]*rkQ.m_afTuple[3];
00244 
00245         kProd.m_afTuple[3] =
00246             m_afTuple[0]*rkQ.m_afTuple[3] +
00247             m_afTuple[3]*rkQ.m_afTuple[0] +
00248             m_afTuple[1]*rkQ.m_afTuple[2] -
00249             m_afTuple[2]*rkQ.m_afTuple[1];
00250 
00251         *this = kProd;
00252 
00253         return *this;
00254 }
00255 
00256 K3dQuaternion& K3dQuaternion::operator* ( float fScalar )
00257 {
00258         for ( int i = 0; i < 4; i++ )
00259                 m_afTuple[i] = fScalar*m_afTuple[i];
00260         return *this;
00261 }
00262 
00263 K3dQuaternion& K3dQuaternion::operator/ ( float fScalar )
00264 {
00265         int i;
00266 
00267         if ( fScalar != ( float ) 0.0 )
00268         {
00269                 float fInvScalar = ( ( float ) 1.0 ) /fScalar;
00270                 for ( i = 0; i < 4; i++ )
00271                         m_afTuple[i] = fInvScalar*m_afTuple[i];
00272         }
00273         else
00274         {
00275                 for ( i = 0; i < 4; i++ )
00276                         m_afTuple[i] = K3dMath::MAX_REAL;
00277         }
00278 
00279         return *this;
00280 }
00281 
00282 K3dQuaternion& K3dQuaternion::operator- ()
00283 {
00284         for ( int i = 0; i < 4; i++ )
00285                 m_afTuple[i] = -m_afTuple[i];
00286         return *this;
00287 }
00288 
00289 K3dQuaternion& K3dQuaternion::operator+= ( K3dQuaternion& rkQ )
00290 {
00291         for ( int i = 0; i < 4; i++ )
00292                 m_afTuple[i] += rkQ.m_afTuple[i];
00293         return *this;
00294 }
00295 
00296 K3dQuaternion& K3dQuaternion::operator-= ( K3dQuaternion& rkQ )
00297 {
00298         for ( int i = 0; i < 4; i++ )
00299                 m_afTuple[i] -= rkQ.m_afTuple[i];
00300         return *this;
00301 }
00302 
00303 K3dQuaternion& K3dQuaternion::operator*= ( float fScalar )
00304 {
00305         for ( int i = 0; i < 4; i++ )
00306                 m_afTuple[i] *= fScalar;
00307         return *this;
00308 }
00309 
00310 K3dQuaternion& K3dQuaternion::operator/= ( float fScalar )
00311 {
00312         int i;
00313 
00314         if ( fScalar != ( float ) 0.0 )
00315         {
00316                 float fInvScalar = ( ( float ) 1.0 ) /fScalar;
00317                 for ( i = 0; i < 4; i++ )
00318                         m_afTuple[i] *= fInvScalar;
00319         }
00320         else
00321         {
00322                 for ( i = 0; i < 4; i++ )
00323                         m_afTuple[i] = K3dMath::MAX_REAL;
00324         }
00325 
00326         return *this;
00327 }
00328 
00329 void K3dQuaternion::FromRotationMatrix ( K3dMatrix& rkRot )
00330 {
00331         // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
00332         // article "Quaternion Calculus and Fast Animation".
00333 
00334         float fTrace = rkRot ( 0,0 ) + rkRot ( 1,1 ) + rkRot ( 2,2 );
00335         float fRoot;
00336 
00337         if ( fTrace > ( float ) 0.0 )
00338         {
00339                 // |w| > 1/2, may as well choose w > 1/2
00340                 fRoot = K3dMath::Sqrt ( fTrace + ( float ) 1.0 );  // 2w
00341                 m_afTuple[0] = ( ( float ) 0.5 ) *fRoot;
00342                 fRoot = ( ( float ) 0.5 ) /fRoot;  // 1/(4w)
00343                 m_afTuple[1] = ( rkRot ( 2,1 )-rkRot ( 1,2 ) ) *fRoot;
00344                 m_afTuple[2] = ( rkRot ( 0,2 )-rkRot ( 2,0 ) ) *fRoot;
00345                 m_afTuple[3] = ( rkRot ( 1,0 )-rkRot ( 0,1 ) ) *fRoot;
00346         }
00347         else
00348         {
00349                 // |w| <= 1/2
00350                 int i = 0;
00351                 if ( rkRot ( 1,1 ) > rkRot ( 0,0 ) )
00352                         i = 1;
00353                 if ( rkRot ( 2,2 ) > rkRot ( i,i ) )
00354                         i = 2;
00355                 int j = NEXT[i];
00356                 int k = NEXT[j];
00357 
00358                 fRoot = K3dMath::Sqrt ( rkRot ( i,i )-rkRot ( j,j )-rkRot ( k,k ) + ( float ) 1.0 );
00359                 float* apfQuat[3] = { &m_afTuple[1], &m_afTuple[2], &m_afTuple[3] };
00360                 *apfQuat[i] = ( ( float ) 0.5 ) *fRoot;
00361                 fRoot = ( ( float ) 0.5 ) /fRoot;
00362                 m_afTuple[0] = ( rkRot ( k,j )-rkRot ( j,k ) ) *fRoot;
00363                 *apfQuat[j] = ( rkRot ( j,i ) +rkRot ( i,j ) ) *fRoot;
00364                 *apfQuat[k] = ( rkRot ( k,i ) +rkRot ( i,k ) ) *fRoot;
00365         }
00366 }
00367 
00369 void K3dQuaternion::ToRotationMatrix ( K3dMatrix& _rkRot )
00370 {
00371         _rkRot[0] = ( 1.0f - 2.0f * m_afTuple[1] * m_afTuple[1] - 2.0f * m_afTuple[2] * m_afTuple[2] );
00372         _rkRot[1] = ( 2.0f * m_afTuple[0] * m_afTuple[1] + 2.0f * m_afTuple[3] * m_afTuple[2] );
00373         _rkRot[2] = ( 2.0f * m_afTuple[0] * m_afTuple[2] - 2.0f * m_afTuple[3] * m_afTuple[1] );
00374 
00375         _rkRot[4] = ( 2.0f * m_afTuple[0] * m_afTuple[1] - 2.0f * m_afTuple[3] * m_afTuple[2] );
00376         _rkRot[5] = ( 1.0f - 2.0f * m_afTuple[0] * m_afTuple[0] - 2.0f * m_afTuple[2] * m_afTuple[2] );
00377         _rkRot[6] = ( 2.0f * m_afTuple[1] * m_afTuple[2] + 2.0f * m_afTuple[3] * m_afTuple[0] );
00378 
00379         _rkRot[8] = ( 2.0f * m_afTuple[0] * m_afTuple[2] + 2.0f * m_afTuple[3] * m_afTuple[1] );
00380         _rkRot[9] = ( 2.0f * m_afTuple[1] * m_afTuple[2] - 2.0f * m_afTuple[3] * m_afTuple[0] );
00381         _rkRot[10] = ( 1.0f - 2.0f * m_afTuple[0] * m_afTuple[0] - 2.0f * m_afTuple[1] * m_afTuple[1] );
00382 }
00383 
00384 void K3dQuaternion::FromRotationMatrix ( K3dVector3 akRotColumn[3] )
00385 {
00386         K3dMatrix kRot;
00387         for ( int iCol = 0; iCol < 3; iCol++ )
00388         {
00389                 kRot ( 0,iCol ) = akRotColumn[iCol][0];
00390                 kRot ( 1,iCol ) = akRotColumn[iCol][1];
00391                 kRot ( 2,iCol ) = akRotColumn[iCol][2];
00392         }
00393         FromRotationMatrix ( kRot );
00394 }
00395 
00396 
00397 void K3dQuaternion::ToRotationMatrix ( K3dVector3 akRotColumn[3] )
00398 {
00399         K3dMatrix kRot;
00400         ToRotationMatrix ( kRot );
00401         for ( int iCol = 0; iCol < 3; iCol++ )
00402         {
00403                 akRotColumn[iCol][0] = kRot ( 0,iCol );
00404                 akRotColumn[iCol][1] = kRot ( 1,iCol );
00405                 akRotColumn[iCol][2] = kRot ( 2,iCol );
00406         }
00407 }
00408 
00409 
00410 
00412 void K3dQuaternion::FromAxisAngle ( K3dVector3 _kAngle )
00413 {
00414         float fAngle;
00415         K3dVector3 kSin, kCos;
00416 
00417         fAngle = _kAngle[0] * 0.5f;
00418         kSin[0] = sin ( fAngle );
00419         kCos[0] = cos ( fAngle );
00420         fAngle = _kAngle[1] * 0.5f;
00421         kSin[1] = sin ( fAngle );
00422         kCos[1] = cos ( fAngle );
00423         fAngle = _kAngle[2] * 0.5f;
00424         kSin[2] = sin ( fAngle );
00425         kCos[2] = cos ( fAngle );
00426 
00427         float fSqrCos = kCos[0] * kCos[1];
00428         float fSqrSin = kSin[0] * kSin[1];
00429 
00430         m_afTuple[0] = ( float ) ( kSin[0] * kCos[1] * kCos[2] - kCos[0] * kSin[1] * kSin[2] );
00431         m_afTuple[1] = ( float ) ( kCos[0] * kSin[1] * kCos[2] + kSin[0] * kCos[1] * kSin[2] );
00432         m_afTuple[2] = ( float ) ( fSqrCos * kSin[2] - fSqrSin * kCos[2] );
00433         m_afTuple[3] = ( float ) ( fSqrCos * kCos[2] + fSqrSin * kSin[2] );
00434 }
00435 
00437 void K3dQuaternion::FromAxisAngle ( K3dVector3& rkAxis, float fAngle )
00438 {
00439         float fHalfAngle = ( ( float ) 0.5 ) *fAngle;
00440         float fSin = K3dMath::Sin ( fHalfAngle );
00441         m_afTuple[0] = K3dMath::Cos ( fHalfAngle );
00442         m_afTuple[1] = fSin*rkAxis[0];
00443         m_afTuple[2] = fSin*rkAxis[1];
00444         m_afTuple[3] = fSin*rkAxis[2];
00445 }
00446 
00448 void K3dQuaternion::ToAxisAngle ( K3dVector3& rkAxis, float& rfAngle )
00449 {
00450         float fSqrLength = m_afTuple[1]*m_afTuple[1] + m_afTuple[2]*m_afTuple[2]
00451                            + m_afTuple[3]*m_afTuple[3];
00452         if ( fSqrLength > K3dMath::EPSILON )
00453         {
00454                 rfAngle = ( ( float ) 2.0 ) *K3dMath::ACos ( m_afTuple[0] );
00455                 float fInvLength = K3dMath::InvSqrt ( fSqrLength );
00456                 rkAxis[0] = m_afTuple[1]*fInvLength;
00457                 rkAxis[1] = m_afTuple[2]*fInvLength;
00458                 rkAxis[2] = m_afTuple[3]*fInvLength;
00459         }
00460         else
00461         {
00462                 // angle is 0 (mod 2*pi), so any axis will do
00463                 rfAngle = ( float ) 0.0;
00464                 rkAxis[0] = ( float ) 1.0;
00465                 rkAxis[1] = ( float ) 0.0;
00466                 rkAxis[2] = ( float ) 0.0;
00467         }
00468 }
00469 
00470 float K3dQuaternion::Dot ( K3dQuaternion& rkQ )
00471 {
00472         float fDot = ( float ) 0.0;
00473         for ( int i = 0; i < 4; i++ )
00474                 fDot += m_afTuple[i]*rkQ.m_afTuple[i];
00475         return fDot;
00476 }
00477 
00478 K3dQuaternion& K3dQuaternion::Inverse ()
00479 {
00480         K3dQuaternion kInverse;
00481 
00482         float fNorm = ( float ) 0.0;
00483         int i;
00484         for ( i = 0; i < 4; i++ )
00485                 fNorm += m_afTuple[i]*m_afTuple[i];
00486 
00487         if ( fNorm > ( float ) 0.0 )
00488         {
00489                 float fInvNorm = ( ( float ) 1.0 ) /fNorm;
00490                 kInverse.m_afTuple[0] = m_afTuple[0]*fInvNorm;
00491                 kInverse.m_afTuple[1] = -m_afTuple[1]*fInvNorm;
00492                 kInverse.m_afTuple[2] = -m_afTuple[2]*fInvNorm;
00493                 kInverse.m_afTuple[3] = -m_afTuple[3]*fInvNorm;
00494         }
00495         else
00496         {
00497                 // return an invalid result to flag the error
00498                 for ( i = 0; i < 4; i++ )
00499                         kInverse.m_afTuple[i] = ( float ) 0.0;
00500         }
00501         *this = kInverse;
00502         return *this;
00503 
00504 }
00505 
00506 K3dQuaternion& K3dQuaternion::Conjugate ()
00507 {
00508         m_afTuple[0] = - m_afTuple[0];
00509         m_afTuple[1] = - m_afTuple[1];
00510         m_afTuple[2] = - m_afTuple[2];
00511 
00512         return *this;
00513 }
00514 
00518 K3dQuaternion& K3dQuaternion::Exp ()
00519 {
00520         K3dQuaternion kResult;
00521 
00522         float fAngle = K3dMath::Sqrt ( m_afTuple[1]*m_afTuple[1] +
00523                                        m_afTuple[2]*m_afTuple[2] + m_afTuple[3]*m_afTuple[3] );
00524 
00525         float fSin = K3dMath::Sin ( fAngle );
00526         kResult.m_afTuple[0] = K3dMath::Cos ( fAngle );
00527 
00528         int i;
00529 
00530         if ( K3dMath::FAbs ( fSin ) >= K3dMath::EPSILON )
00531         {
00532                 float fCoeff = fSin/fAngle;
00533                 for ( i = 1; i <= 3; i++ )
00534                         kResult.m_afTuple[i] = fCoeff*m_afTuple[i];
00535         }
00536         else
00537         {
00538                 for ( i = 1; i <= 3; i++ )
00539                         kResult.m_afTuple[i] = m_afTuple[i];
00540         }
00541         *this = kResult;
00542         return *this;
00543 }
00544 
00548 K3dQuaternion& K3dQuaternion::Log ()
00549 {
00550         K3dQuaternion kResult;
00551         kResult.m_afTuple[0] = ( float ) 0.0;
00552 
00553         int i;
00554 
00555         if ( K3dMath::FAbs ( m_afTuple[0] ) < ( float ) 1.0 )
00556         {
00557                 float fAngle = K3dMath::ACos ( m_afTuple[0] );
00558                 float fSin = K3dMath::Sin ( fAngle );
00559                 if ( K3dMath::FAbs ( fSin ) >= K3dMath::EPSILON )
00560                 {
00561                         float fCoeff = fAngle/fSin;
00562                         for ( i = 1; i <= 3; i++ )
00563                                 kResult.m_afTuple[i] = fCoeff*m_afTuple[i];
00564                         *this = kResult;
00565                         return *this;
00566                 }
00567         }
00568 
00569         for ( i = 1; i <= 3; i++ )
00570                 kResult.m_afTuple[i] = m_afTuple[i];
00571         *this = kResult;
00572         return *this;
00573 }
00574 
00592 K3dVector3& K3dQuaternion::operator* ( K3dVector3& rkVector )
00593 {
00594         K3dMatrix kRot;
00595         ToRotationMatrix ( kRot );
00596         rkVector = kRot*rkVector;
00597         return rkVector;
00598 }
00599 
00600 
00601 K3dQuaternion& K3dQuaternion::Slerp ( float fT, K3dQuaternion& rkP, K3dQuaternion& rkQ )
00602 {
00603         float fCos = rkP.Dot ( rkQ );
00604         float fAngle = K3dMath::ACos ( fCos );
00605 
00606         if ( K3dMath::FAbs ( fAngle ) < K3dMath::EPSILON )
00607                 return rkP;
00608 
00609         float fSin = K3dMath::Sin ( fAngle );
00610         float fInvSin = ( ( float ) 1.0 ) /fSin;
00611         float fCoeff0 = K3dMath::Sin ( ( ( ( float ) 1.0 )-fT ) *fAngle ) *fInvSin;
00612         float fCoeff1 = K3dMath::Sin ( fT*fAngle ) *fInvSin;
00613         rkP = rkP*fCoeff0;
00614         rkQ = rkQ*fCoeff1;
00615 
00616         return rkP + rkQ;
00617 }
00618 
00619 
00620 K3dQuaternion& K3dQuaternion::SlerpExtraSpins ( float fT,
00621         K3dQuaternion& rkP, K3dQuaternion& rkQ, int iExtraSpins )
00622 {
00623         float fCos = rkP.Dot ( rkQ );
00624         float fAngle = K3dMath::ACos ( fCos );
00625 
00626         if ( K3dMath::FAbs ( fAngle ) < K3dMath::EPSILON )
00627                 return rkP;
00628 
00629         float fSin = K3dMath::Sin ( fAngle );
00630         float fPhase = K3dMath::K_PI*iExtraSpins*fT;
00631         float fInvSin = ( ( float ) 1.0 ) /fSin;
00632         float fCoeff0 = K3dMath::Sin ( ( ( ( float ) 1.0 )-fT ) *fAngle-fPhase ) *fInvSin;
00633         float fCoeff1 = K3dMath::Sin ( fT*fAngle + fPhase ) *fInvSin;
00634         return rkP*fCoeff0 + rkQ*fCoeff1;
00635 }
00636 
00637 
00638 K3dQuaternion& K3dQuaternion::GetIntermediate ( K3dQuaternion& rkQ0,
00639         K3dQuaternion& rkQ1, K3dQuaternion& rkQ2 )
00640 {
00641         K3dQuaternion kQ1Inv = rkQ1.Conjugate();
00642         K3dQuaternion kP0 = kQ1Inv*rkQ0;
00643         K3dQuaternion kP2 = kQ1Inv*rkQ2;
00644         K3dQuaternion kArg = - ( ( kP0.Log() * ( float ) 0.25 ) +kP2.Log() );
00645         K3dQuaternion kA = rkQ1*kArg.Exp();
00646         *this = kA;
00647         return *this;
00648 }
00649 
00650 
00651 K3dQuaternion& K3dQuaternion::Squad ( float fT,  K3dQuaternion& rkQ0,
00652                                       K3dQuaternion& rkA0,  K3dQuaternion& rkA1,  K3dQuaternion& rkQ1 )
00653 {
00654         float fSlerpT = ( ( float ) 2.0 ) *fT* ( ( ( float ) 1.0 )-fT );
00655         K3dQuaternion kSlerpP = Slerp ( fT,rkQ0,rkQ1 );
00656         K3dQuaternion kSlerpQ = Slerp ( fT,rkA0,rkA1 );
00657         return Slerp ( fSlerpT,kSlerpP,kSlerpQ );
00658 }
00659 
00660 
00662 void K3dQuaternion::GetValue ( K3dMatrix & rkMatrix )
00663 {
00664         float s, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
00665 
00666         float fNorm = m_afTuple[0] * m_afTuple[0] + m_afTuple[1] * m_afTuple[1] + m_afTuple[2] * m_afTuple[2] + m_afTuple[3] * m_afTuple[3];
00667 
00668         s = ( EQUIVALENT ( fNorm, ( float ) 0 ) ) ? ( float ) 0 : ( ( float ) 2 / fNorm );
00669 
00670         xs = m_afTuple[0] * s;
00671         ys = m_afTuple[1] * s;
00672         zs = m_afTuple[2] * s;
00673 
00674         wx = m_afTuple[3] * xs;
00675         wy = m_afTuple[3] * ys;
00676         wz = m_afTuple[3] * zs;
00677 
00678         xx = m_afTuple[0] * xs;
00679         xy = m_afTuple[0] * ys;
00680         xz = m_afTuple[0] * zs;
00681 
00682         yy = m_afTuple[1] * ys;
00683         yz = m_afTuple[1] * zs;
00684         zz = m_afTuple[2] * zs;
00685 
00686         rkMatrix ( 0,0 ) = float ( ( float ) 1 - ( yy + zz ) );
00687         rkMatrix ( 1,0 ) = float ( xy + wz );
00688         rkMatrix ( 2,0 ) = float ( xz - wy );
00689 
00690         rkMatrix ( 0,1 ) = float ( xy - wz );
00691         rkMatrix ( 1,1 ) = float ( ( float ) 1 - ( xx + zz ) );
00692         rkMatrix ( 2,1 ) = float ( yz + wx );
00693 
00694         rkMatrix ( 0,2 ) = float ( xz + wy );
00695         rkMatrix ( 1,2 ) = float ( yz - wx );
00696         rkMatrix ( 2,2 ) = float ( ( float ) 1 - ( xx + yy ) );
00697 
00698         rkMatrix ( 3,0 ) = rkMatrix ( 3,1 ) = rkMatrix ( 3,2 ) = rkMatrix ( 0,3 ) = rkMatrix ( 1,3 ) = rkMatrix ( 2,3 ) = ( float ) 0;
00699         rkMatrix ( 3,3 ) = ( float ) 1;
00700 }
00701 
00703 
00704 const float K3dQuaternion::IDENTITY[4] = {1.0f,0.0f,0.0f,0.0f};
00705 const float K3dQuaternion::ZERO[4] = {0.0f,0.0f,0.0f,0.0f};
00706 const int K3dQuaternion::NEXT[3] = { 1, 2, 0 };
00707 
00708 

Generated on Thu Aug 16 23:53:27 2007 for K3dEngine by  doxygen 1.5.0